我在BackgroundWorker
中运行了一项长任务,通过ReportProgress
更新了用户界面。但是,在进程的中间,我需要进行COM调用以获取一些数据,我想我需要在UI线程上进行。我试过通过Control.Invoke这样做。但是,我陷入僵局。不能在Control.Invoke
(BackgroundWorker
)中使用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;
}
没有例外,UI不断更新,但它会停止进展。 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中是否有一些锁定?
答案 0 :(得分:0)
猜测,因为我不知道COM对象的作用或要求:
COM对象需要UI htread的原因可能是因为(在大多数情况下)UI线程被标记为STA线程。
如果COM对象需要单线程公寓,则可以使用标记为STA线程的非UI线程。这样你就不再声称UI线程了。
请参阅:Could you explain STA and MTA?