有没有办法解决这个错误“调用线程无法访问此对象,因为不同的线程拥有它”而不使用调度程序,因为当代码有更长的处理时间时,调度程序会导致UI冻结,还有另一种方法可以做它?不会导致UI冻结
答案 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
帮助你到:
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
。