我尝试做的是执行由MainWindow上的按钮事件触发的繁重任务,但仍然可以自由拖动窗口。我已经尝试了async / await模式和创建新线程。但是,线程将是非阻塞的,MainWindow仍会冻结。这是代码:
uiTIN.Click += async (o, e) =>
{
var _ = await Task.Run(() => job());
};
这是按钮回调,这里是func:
private int job()
{
this.Dispatcher.Invoke(() =>
{
//Other function calls here omitted
});
return 0;
}
编辑:解决方法是使用BackgroundWorker,我还在Dispatcher Invoke函数中修饰了相关的UI代码片段
答案 0 :(得分:2)
来自Dispatcher上的Microsoft's doccumentation(强调我的):
在WPF中,
DispatcherObject
只能由与其关联的Dispatcher
访问。例如,后台线程无法更新与UI线程上的Button
关联的Dispatcher
的内容。 为了让后台线程访问Button的Content
属性,后台线程必须将工作委托给与UI线程关联的Dispatcher
。这是通过使用Invoke
或BeginInvoke
来完成的。Invoke
是同步的,BeginInvoke
是异步的。该操作将添加到指定Dispatcher
的{{1}}队列中。
所以基本上你正在做的是调用一个异步方法,然后强制它在UI线程上运行,它什么都不做。
在DispatcherPriority
中,我认为您需要访问界面的某些部分,如果情况并非如此,您只需删除{{1}从你的方法。
如果我的假设是正确的,那么你必须想出一种分割你的功能的方法,这样不与UI相关的部分在后台线程中运行,而只需要在UI线程上运行的部分实际上做了
我的建议是使用Background Worker
。以下是它的外观:
//Other function calls here omitted
......然后......
Dispatcher.Invoke
答案 1 :(得分:0)
通常的做法是你必须尽快从onClick事件回调按钮返回,以避免阻塞主线程(或者某些引用UI线程)。如果主线程被阻止,应用程序将看起来像冻结。这是用于同步UI流的任何GUI应用程序的基本设计。
您在回调中启动异步任务,但在返回之前还要等待任务完成。您应该在onClick事件中启动BackgroundWorker然后返回。
答案 2 :(得分:0)
已经很好地解释了为什么你的代码阻塞了UI线程(在Dispatcher上排队你的工作)。但我不建议使用BackgroundWorker
,我宁愿使用Task.Run
修复您的代码,原因有几个,本文将对此进行解释:https://blog.stephencleary.com/2013/09/taskrun-vs-backgroundworker-conclusion.html