我正在运行一个很长的任务,BackgroundWorker
通过ReportProgress
. 但是,在这个过程的中间,我需要进行 COM 调用以获取一些数据,并且我认为我需要在 UI 线程上进行。我尝试通过 Control.Invoke 执行此操作。但是,我遇到了僵局。不能Control.Invoke
在BackgroundWorker
(with ShowDialog
) 中使用吗?
我试图简化代码:
var log = new LogWindowForm();
worker.DoWork += (sender, args) =>
{
creator.LogProgress = (s, i) => worker.ReportProgress(i,s);
creator.GetMoreDataFunc = (s) => InvokeGetMoreDataOnGuiThread(log, s);
...
var data = GetMoreDataFunc("id:"+id)
};
worker.RunWorkerAsync();
log.ShowDialog();
private Dictionary<string, string> InvokeGetMoreDataOnGuiThread(Control invokeControl, string id)
{
var data = new Dictionary<string, string>();
Action action = () => data = GetMoreDataFromComObject(mainComObject, id);
invokeControl.Invoke(action); // deadlock!
return data;
}
编辑:
没有例外,用户界面不断更新,但它停止了进步。Break All 显示 Control.Invoke 调用中的工作线程和 ShowDialog 调用中某处的 GUI 线程。
GUI 线程似乎在消息循环中:
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x65 bytes
我想这就是 UI 不断更新的原因。BackgroundWorker 内部是否有一些锁定?