调用线程无法访问此对象,因为另一个线程拥有它wpf

use*_*076 1 wpf multithreading task-parallel-library

我是线程概念的新手.

我已经检查了相同内容的问题,但无法解决我当前的问题,即

我在UI中有一个文本框绑定到MyViewModel.cs中的GridSize当网格大小发生变化时,有一个繁重的计算更新UI组件,使应用程序冻结,所以我尝试使用TPL Task.Factory.StartNew().

这给了我错误"调用线程无法访问此对象,因为另一个线程拥有"

我正在使用MEF导入ViewModel.

Xaml.cs文件

[Import]
public MyViewModel ViewModel
{
  get { return DataContext as MyViewModel; }
  set
  {
    if (DataContext is MyViewModel)
          ViewModel.OnModelUpdated -= ModelUpdatedEvent;

     DataContext = value;

     if (DataContext is MyViewModel)
     {
       ViewModel.OnModelUpdated += ModelUpdatedEvent;
     }
   }
}

private void ModelUpdatedEvent(object sender, EventArgs e)
{
   // code to update the UI.
}
Run Code Online (Sandbox Code Playgroud)

MyViewModel.cs

public double GridSize
{
   get { return _settings.GridSize; }
   set
   {
       _settings.GridSize = value;

       ModelUpdatedEvent();
   }
}

public event EventHandler OnModelUpdated;

public void ModelUpdatedEvent()
{
    EventHandler eventModelUpdated = OnModelUpdated;
    if (eventModelUpdated != null)
    {
       Task.Factory.StartNew(()=> eventModelUpdated.Invoke(this, EventArgs.Empty));
    }
}
Run Code Online (Sandbox Code Playgroud)

任何帮助深表感谢.

Gaz*_*yer 7

WPF可视对象只能由创建它们的线程来操作.TPL通过使用其他线程并行执行.

您可以使用以下方法将计算结果编组回正确的线程Dispatcher.BeginInvoke():

Application.Current.Dispatcher.BeginInvoke(new Action(() => this.GridSize = calculatedGridSize));
Run Code Online (Sandbox Code Playgroud)

根据你的评论.如果您的阻塞计算在视图中,那么您仍然需要将这些计算卸载到后面的代码中的另一个线程.您需要从实际触及视图项的代码中拆分实际计算.完成计算后,您需要以上述方式编组对可视项目的任何调用.