而不是在后台工作 - 此代码仍然冻结我的程序:
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";
}));
});
}
,我的程序仍然在冻结。有任何建议吗?
Dispatcher
类的文档:
提供用于管理线程队列的服务。
来自Dispatcher.BeginInvoke
的文档:
用在线程上的指定参数上执行指定的委托,以创建调度程序。
在这里"异步"&quot'是指次要线程,而不是主要线程。因为主要调度员拥有主要的。这意味着该调度程序上的Invoke
或BeginInvoke
的每个呼叫,从任何线程中,都会将被调用的操作放在主线程必须执行的操作队列中,但是从主线程的角度来看,它们将同步执行,一个接一个。
例如,如果您在调度器上10毫秒内将3个 Thread.Sleep(1000);
这样的操作,无论是使用Invoke
还是BeginInvoke
,以及是否是否从线程中,该调度程序将使UI线程同时执行3个操作,以便他们进行总计3000 ms。
也许关于BeginInvoke
的文档可能已经写得更好,例如:
用在创建调度程序的线程上的指定参数执行指定的委托。指定的委托从调用线程的角度异步执行。
现在... Invoke
或BeginInvoke
?
使用Invoke
,辅助线程对调度程序说:让我们在主线程上执行此操作,并且直到线程的作业完成之前,请不要敢返回。然后,我才会继续。
例如,如果您写这篇文章:
this.Dispatcher.Invoke(new Action(() =>
{
Thread.Sleep(5000);
Debug.WriteLine("After Sleep");
}));
Debug.WriteLine("Continuation on secondary Thread");
控制台将在〜5000 ms之后打印:
"睡眠后"
'在辅助线程上延续'
使用BeginInvoke
,该线程说:'嘿,调度员,在主线程上排队此操作,但尽快返回,以便我可以立即继续工作&quot&quot&quot; <<<<<</em> <</p>
在这种情况下,控制台将立即打印:
'在辅助线程上延续'
和〜5000 ms之后:
"睡眠后"
现在,如果您的目的是在后台执行一些重型操作,则应了解异步/等待模式,可从.NET 4.5和C#5.0获得。
在您的示例中,我会写:
private async void button_Click(object sender, RoutedEventArgs e)
{
await Task.Delay(5000); // await a heavy operation executed in background
label.Content = "Done"; // control back to the UI Thread that executes this
}
如果您的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";
});
}