解决调用线程无法访问此对象,因为另一个线程拥有它错误不使用Dispatcher

时间:2014-06-30 04:09:08

标签: c# wpf

有没有办法解决这个错误“调用线程无法访问此对象,因为不同的线程拥有它”而不使用调度程序,因为当代码有更长的处理时间时,调度程序会导致UI冻结,还有另一种方法可以做它?不会导致UI冻结

2 个答案:

答案 0 :(得分:6)

不,您必须更新UI线程上的UIElement,如错误所示。

是的,除了使用Dispatcher之外,还有其他方法可以在UI线程上运行某些东西,但他们喜欢Dispatcher仍然可以运行你想要在UI线程上运行的东西 - 所以将仍然冻结用户界面。

如果您使用的是C#5和.NET 4.5或更高版本,您可以轻松运行长时间运行的进程,而不会阻止UI线程,然后在UI线程上完成继续(不用担心它是如何工作的)使用{{1 }和async关键字:

await

如果你没有这些,那么你会想要使用 private async Task<string> SimLongRunningProcessAsync() { await Task.Delay(2000); return "Success"; } private async void Button_Click(object sender, RoutedEventArgs e) { button.Content = "Running..."; var result = await SimLongRunningProcessAsync(); button.Content = result; } Dispatcher实际上可以帮助您在不冻结UI的情况下运行流程

你想要做的是运行长时间运行的进程关闭 UI线程,然后运行更新用户界面 - Dispatcher帮助你到:

  1. 在另一个线程上启动long进程并立即返回。
  2. (长流程仍在运行,UI继续更新)
  3. 长处理完成,更新UI线程上的UI。
  4. e.g:

    Dispatcher

答案 1 :(得分:1)

如果您使用的是.NET 4.0或更高版本,则可以将async and await keywords用于干净的异步代码。此功能直接内置于4.5中,而对于4.0,可以使用Microsoft(Microsoft.Bcl.Async)提供的NuGet包来启用此功能。

例如,用户点击一个按钮,您希望做一些可能需要一些时间的事情,然后向用户报告。

// Notice how this method is marked 'async', this allows the 'await' keyword
async void OnButtonClicked(object sender, EventArgs e)
{
   var button = sender as Button;

   button.IsEnabled = false;
   button.Text = "Calculating...";

   int result = await DoSomeWork();

   button.IsEnabled = true;
   button.Text = "Calculate";
}

// This is an asynchronous method that returns an integer result
Task<int> DoSomeWork()
{
   // Do some lengthy computation here, will be run on a background thread
   return 42;
}

或者,您可以使用其他机制,例如BackgroundWorker类,或Asynchronous Programming Model (APM)使用回调。这些都很好,但async / await模式更可取。

如果您有选择,请定位.NET 4.5(Win7 +)。如果您还必须支持Windows XP,请以.NET 4.0为目标并使用NuGet包Microsoft.Bcl.Async