gpt4 book ai didi

c# - WPF Dispatcher 线程卡住主窗口

转载 作者:太空宇宙 更新时间:2023-11-03 18:55:35 32 4
gpt4 key购买 nike

而不是在后台工作——这段代码仍然卡住我的程序:

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";
}));
});
}

而且我的程序仍然卡住。有什么建议吗?

最佳答案

来自documentation Dispatcher 类的:

Provides services for managing the queue of work items for a thread.

来自documentation Dispatcher.BeginInvoke 的:

Executes the specified delegate asynchronously with the specified arguments on the thread that the Dispatcher was created on.

这里“异步”指的是副线程,不是主线程。因为主要的归主 Dispatcher 所有。这意味着每次从任何线程调用该 Dispatcher 上的 InvokeBeginInvoke 都会将调用的 Action 放入主线程必须执行的操作队列中,但是从从主线程的角度来看,它们将同步执行,一个接一个地执行。

例如,如果您在 Dispatcher 的 10 毫秒内放置 3 个类似 Thread.Sleep(1000); 的 Action,无论是 Invoke 还是 BeginInvoke 从是否是 Thread,Dispatcher 会让 UI Thread 同步执行 3 个 Action,所以总共需要 3000 ms。

也许关于 BeginInvoke 的文档可以写得更好,比如:

Executes the specified delegate with the specified arguments on the thread that the Dispatcher was created on. The specified delegate is executed asynchronously from the point of view of the calling thread.

现在... Invoke 还是 BeginInvoke

使用 Invoke,辅助线程对调度程序说:让我们在主线程上执行它,并且在您的线程的工作完成之前不敢返回。然后,只有到那时,我才会继续

例如,如果你这样写:

this.Dispatcher.Invoke(new Action(() =>
{
Thread.Sleep(5000);
Debug.WriteLine("After Sleep");
}));
Debug.WriteLine("Continuation on secondary Thread");

控制台将在约 5000 毫秒后打印:

"After Sleep"

"Continuation on secondary Thread"

相反,使用 BeginInvoke,线程会说:“嘿,Dispatcher,在主线程上将此操作排队,但尽快返回以便我可以立即继续我的工作” .

在这种情况下,控制台将立即打印:

"Continuation on secondary Thread"

在 ~ 5000 毫秒之后:

"After Sleep"


现在,如果您的目的是在后台执行一些繁重的操作,您应该了解 .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
}

关于c# - WPF Dispatcher 线程卡住主窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46253657/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com