在WPF应用程序(C#,.NET 4.0,VS 2013)中,以下代码(从UI线程调用)冻结UI线程1秒钟:
new Thread(new ThreadStart(() =>
{
Dispatcher.BeginInvoke(new Action(() =>
{
Thread.Sleep(1000);
}));
})).Start();
Thread.Sleep()
是一个占位符。在实际代码中,它将访问一些UI元素并进行一些耗时的计算。这也在UI线程上运行!
它不应该在UI线程以外的其他线程中运行吗?我错过了什么?
答案 0 :(得分:4)
Dispatcher.BeginInvoke
旨在将操作(通过委托)推送到UI线程。你已经告诉它将Thread.Sleep(1000)
推送到UI线程,所以是的:UI线程将冻结。
例如,从主UI线程分离出来的后台线程无法更新在UI线程上创建的Button的内容。为了让后台线程访问Button的Content属性,后台线程必须将工作委托给与UI线程关联的Dispatcher。这是通过使用Invoke或BeginInvoke来完成的。 Invoke是同步的,BeginInvoke是异步的。
如果您想在后台完成工作...... 您已经在后台线程(在致电Dispatcher.BeginInvoke
之前)。
我怀疑你在这里应该做的是:
.Invoke
从UI收集值到工作人员.Invoke
或.BeginInvoke
更新用户界面答案 1 :(得分:1)
Dispatcher.BeginInvoke在主线程上执行操作。使用它来执行你的线程:
new Thread(new ThreadStart(() =>
{
{
Thread.Sleep(1000);
};
})).Start();
答案 2 :(得分:1)
就像Marc已经说Dispatcher.BeginInvoke()将Action中的所有代码都推送到UI线程所以如果你希望你的UI保持响应,代码就会在那里执行,在你调用Dispatcher.Begin Invoke之前执行计算然后在BeginInvoke中设置UI控件。
new Thread(new ThreadStart(() =>
{
int result = MyHeavyCalculation();
Dispatcher.BeginInvoke(new Action(() =>
{
label1.Text = result.ToString();
}));
})).Start();
或者看看async-await以异步方式执行方法,而不必为自己的UI线程同步而烦恼。 Simple Example