c# - 在另一个线程中创建 WPF 命令

标签 c# wpf multithreading mvvm

我目前正在开发一个登录窗口,它应该负责建立与服务器的连接,验证用户凭据,然后打开一个 MVVM 'MainWindow'。我想稍微加快 MainWindow 的打开过程,这就是为什么我试图将其 ViewModel 的初始化转移到自己的 Task 中。 .这不知何故破坏了我的命令,我不明白为什么,所以我创建了一个 最小可重现示例 解释我的问题。ViewModel看起来像这样:

public class MainWindowViewModel
  {

    public MainWindowViewModel()
    {
        

    }

    public ICommand ClickCommand { get; set; }

    public void CreateCommands()
    {
      ClickCommand = new RelayCommand(ExecuteClick);
    }


    public void ExecuteClick()
    {

    }
View只是一个带有命令绑定(bind)按钮的默认窗口:Command="{Binding ClickCommand}"我创建 View 和 View 模型并调用 CreateCommands从一个有效的任务中。
  MainWindow mw = new MainWindow();

  MainWindowViewModel vm = new MainWindowViewModel();
  mw.DataContext = vm;
   
  Task.Run(() =>
  {
   vm.CreateCommands();

  });
  mw.ShowDialog();
现在我创建一个新方法 Init()在我看来并让它调用CreateCommands() .只要我打电话Init()而不是 CreateCommands()在我的任务中,如下所示。 ExecuteClick()当我按下按钮时不会被调用。
public void Init()
{
   ((MainWindowViewModel)DataContext).CreateCommands();
}
--
  Task.Run(() =>
  {
   mw.Init();

  });
自从调用 mw.Init()如果没有任务工作,我怀疑 WPF 调度程序有问题,所以我尝试使用 App.Current.Dispatcher.BeginInvoke(new Action(() =>mw.Init()));Invoke ,但这并没有改变任何东西。我还尝试在放置 Init() 时复制此行为Mehtod 在其他 UI 元素中,但从另一个窗口调用它会再次起作用:
public Window1()
{
  InitializeComponent();

  MainWindow mw = new MainWindow();

  MainWindowViewModel vm = new MainWindowViewModel();
  mw.DataContext = vm;
   
  Task.Run(() =>
  {
   Init(vm);

  });
  mw.ShowDialog();


}

public void Init(MainWindowViewModel vm)
{
  vm.CreateCommands();
}
我还尝试了 Core 和 Framework 之间的差异,或者将我的 ViewModel 保存在成员变量中,而不是使用 DataContext ,没有任何显着差异。
究竟会发生什么,这会阻止我的命令仅在通过 View 在线程中创建它们时才被创建?

最佳答案

优化前的配置文件
问题是主窗口打开速度很慢。您是否分析并得出结论是命令创建是主要瓶颈?如果没有,就从那开始。
wpf是单线程的
WPF(和大多数其他 UI 框架)基本上是单线程的。这意味着只能从 UI 线程访问任何 UI 对象。仍然可以在后台进行一些初始化,但是任何导致 UI 更新的事情都必须在 UI 线程上完成。
如果有一些缓慢的后台工作,典型的方法是在后台线程上做缓慢的事情,当这完成后,在 UI 线程上进行 UI 更新。这可以使用 async/await 轻松完成。
View 模型更新时没有通知
View 模型应该实现 INotifyPropertyChanged任何更改都应提高 PropertyChanged事件。您的示例中没有这样做。这可能是使用任务对您不起作用的原因,因为 View 绑定(bind)可能不会更新。

关于c# - 在另一个线程中创建 WPF 命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64804914/

相关文章:

wpf - 删除XAML使用的图像文件

java - JavaFX 8图形线程管道

c# - 如何在 MVVM 中处理动态按钮中的执行和可以执行条件

c# - UWP:替代 Grid.IsSharedSizeScope 和 SharedSizeGroup

Java 同步实例成员不能以嵌套方式工作

java - 聊天:向服务器上的所有客户端发送消息

c# - 在调用方法时使用 Moq 分配属性值

c# - AutoMapper 定义映射级别

c# - 如何获取有关 Frame.GoBack() 上一页的信息

c# - Silverlight和等待失败