而不是在后台工作 - 这段代码仍然冻结我的程序:
private void button_Click(object sender, RoutedEventArgs e)
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
Thread.Sleep(5000);
label.Content = "Done";
}), DispatcherPriority.Normal);
}
我尝试使用线程/任务,线程示例:
private void button_Click(object sender, RoutedEventArgs e)
{
var t = new Thread(new ThreadStart(runtask));
t.Start();
}
private void runtask()
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
Thread.Sleep(5000);
label.Content = "Done";
}), DispatcherPriority.Normal);
}
任务示例:
private void button_Click(object sender, RoutedEventArgs e)
{
Task.Run(() =>
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() =>
{
Thread.Sleep(5000);
label.Content = "Done";
}));
});
}
我的节目仍然冻结。有什么建议吗?
答案 0 :(得分:7)
来自Dispatcher
班级的documentation:
提供管理线程工作项队列的服务。
来自Dispatcher.BeginInvoke
的{{3}}:
使用创建Dispatcher的线程上的指定参数异步执行指定的委托。
这里“异步”指的是辅助线程,而不是主要线程。因为主要的一个由主Dispatcher拥有。这意味着每个调用Invoke
或BeginInvoke
在该调度程序上,从任何线程调用,都会将调用的Action放入主线程必须执行的操作队列中,但是从该角度来看主线程它们将一个接一个地同步执行。
例如,如果你在Dispatcher上放置了10 {10}之内的3个Action,无论是Thread.Sleep(1000);
还是Invoke
,还是来自Thread,那个Dispatcher会将UI线程设置为同步执行3 Action,总共需要3000 ms。
也许有关BeginInvoke
的文档可以更好地编写,例如:
在创建Dispatcher的线程上执行具有指定参数的指定委托。从调用线程的角度来看,指定的委托是异步执行的。
现在...... BeginInvoke
或Invoke
?
使用BeginInvoke
,辅助线程向Dispatcher说:让我们在主线程上执行此操作,并且在线程的作业完成之前不敢返回。然后我才会继续。
例如,如果你这样写:
Invoke
控制台将在~5000毫秒后打印:
“睡眠后”
“继续使用辅助线程”
使用this.Dispatcher.Invoke(new Action(() =>
{
Thread.Sleep(5000);
Debug.WriteLine("After Sleep");
}));
Debug.WriteLine("Continuation on secondary Thread");
,而线程正在说:“嘿,Dispatcher,在主线程上对此操作进行排队,但是尽快返回,以便我可以立即继续我的工作”
在这种情况下,控制台将立即打印:
“继续使用辅助线程”
大约5000毫秒后:
“睡眠后”
现在,如果您的目的是在后台执行一些繁重的操作,您应该了解.NET 4.5和C#5.0中提供的async / await模式。
在你的例子中,我会写:
BeginInvoke
答案 1 :(得分:-1)
如果您的UI访问是最后一种方法,则可以使用此小扩展名。
https://mitsufu.wordpress.com/2015/08/03/dispatcher-switchto/
private void Button_Click(object sender, RoutedEventArgs e)
{
Task.Run(async () =>
{
//heavy background operation
await Dispatcher.SwitchTo();
Title = "ok";
});
}