Eri*_*tas 11 c# multithreading thread-safety winforms
我正在为另一个程序编写一个插件,该程序使用本机程序打开一系列文件以从中提取一些数据.我遇到的一个问题是该过程需要很长时间,我想保持用户界面不挂.另外,我还想让用户在完成之前取消该过程.在过去,我使用后台工作者来处理这类事情,但在这种情况下,我认为BackgroundWorker不会起作用.
要通过API创建插件,我使用的可以通过继承IAPICommand接口来创建自定义命令.该接口包括Execute(应用程序app)方法.然后实例化该类,当用户在程序中唤起自定义命令时,程序将调用Execute()方法.
Execute()方法在调用时传递对当前Application对象的引用,并且该应用程序对象用于打开文件以从中提取数据.但是,应用程序实例无法在原始Execute()线程之外的线程请求时打开文档.
因此,通常UI将存在于主线程上,并且将在辅助线程上执行耗时的数据提取.但是,在这种情况下,必须在主线程上执行数据提取,并且我需要为UI创建辅助线程.
这是代码的精简版本.
class MyCommand:IAPICommand
{
public void Execute(Application app) // method from IAPICommand
{
Thread threadTwo= new Thread(ShowFormMethod);
threadTwo.Start();
}
public void ProcessWidget(Widget w, Application app)
{
//uses an App to work some magic on C
//app must be called from the original thread that called ExecuteCommand()
}
//method to open custom form on a seperatethread
public void ShowFormMethod()
{
MyForm form = new MyForm();
form.ShowDialog();
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个流程图,显示了我认为这应该最终起作用的方式.
alt text http://dl.dropbox.com/u/113068/SOMLibThreadingDiagram.jpg
Joh*_*ler 14
在应用程序中创建多个创建表单的线程通常是个坏主意.使这项工作并非不可能,但它比你想象的要困难得多,因为父子关系中的表单会相互发送消息,而当它们发送消息时,发送消息的表会阻塞接收处理它.
将此信息与您明确执行的线程之间的消息传递或同步相结合,并且很容易导致死锁.因此,一般情况下,最好确保为用户界面保留主线程,并在没有UI的其他线程中执行所有处理.
如果符合该设计,则后台线程可以使用Control.BeginInvoke将消息传递给UI线程,而无需等待消息处理.
我假设主机应用程序是 WinForms 应用程序。
您需要在方法中保存原始线程中的SynchronizationContextExecute,然后调用其Send方法在主机的 UI 线程上执行代码。
例如:
class MyCommand:IAPICommand
{
SynchronzationContext hostContext;
public void Execute(Application app) // method from IAPICommand
{
hostContext = SynchronzationContext.Current;
Thread threadTwo = new Thread(ShowFormMethod);
threadTwo.Start();
}
public void ProcessWidget(Widget w, Application app)
{
//uses an App to work some magic on C
//app must be called from the original thread that called ExecuteCommand()
SomeType someData = null;
hostContext.Send(delegate { someData = app.SomeMethod(); }, null);
}
}
Run Code Online (Sandbox Code Playgroud)