C#中的跨线程事件处理 [英] Cross-thread event handling in C#
问题描述
class SomeDataSource {
public event OnFrameworkEvent;
void FrameworkCallback(){
//此函数运行在框架的线程上。
if(OnFrameworkEvent!= null)
OnFrameworkEvent(args);
}
}
我想将这些事件传递给Winforms对象Winforms线程。我明显地检查 InvokeRequired
,并在必要时将其发送到Winforms线程。
class SomeForm:Form {
// ...
public void SomeAction(SomeArgs args){
if(InvokeRequired){
BeginInvoke new Action(SomeAction),args);
return;
}
// ...
}
}
现在,当表单处于关闭状态时,可能会发送事件,从而导致各种问题,所以我就像Winforms线程从框架的事件源注销窗体的事件处理程序:
var form = new SomeForm();
var src = new SomeDataSource();
// ...
src.OnFrameworkEvent + = form.SomeAction;
form.Closing + =(sender,eargs)=> src.OnFrameworkEvent - = form.SomeAction;
-
现在,这种方法线程安全?如果表单处于关闭状态,外线调用
BeginInvoke
,表单关闭后,调用是否仍然排队等待执行? (这意味着我仍然有机会遇到相同的问题) -
是否有更好的方法或推荐的跨线程事件处理模式?
不是。线程可能正在执行事件处理程序,而您注销它并关闭窗体。小赔率,但不是零。您必须先停止线程才能关闭窗体。如果你不想中止它,你必须通过取消FormClosing事件来保持表单的打开,然后让线程的完成回调关闭窗体。
有关详细信息,请查看此主题。
I am working with a framework that runs its own event dispatcher in a separate thread. The framework may generate some events.
class SomeDataSource {
public event OnFrameworkEvent;
void FrameworkCallback() {
// This function runs on framework's thread.
if (OnFrameworkEvent != null)
OnFrameworkEvent(args);
}
}
I want to deliver these events to a Winforms object on Winforms thread. I obviously check for InvokeRequired
and dispatch it to Winforms thread if necessary.
class SomeForm : Form {
// ...
public void SomeAction(SomeArgs args) {
if (InvokeRequired) {
BeginInvoke(new Action(SomeAction), args);
return;
}
// ...
}
}
Now events may be delivered when the form is in the process of being closed, which causes all sorts of problems, so I unregister the form's event handler from framework's event source on Winforms thread like this:
var form = new SomeForm();
var src = new SomeDataSource();
// ...
src.OnFrameworkEvent += form.SomeAction;
form.Closing += (sender, eargs) => src.OnFrameworkEvent -= form.SomeAction;
Now, is this approach thread-safe? If the form is in the process of being closed, and a foreign thread calls
BeginInvoke
, will the invocation still be queued for execution if the form is closed? (which means I still have a chance of encountering the same problem)Is there a better approach or recommended pattern for cross-thread event handling?
No it is not. The thread might just be executing the event handler while you unregister it and close the form. Small odds, but not zero. You have to have the thread stopped before you can close the form. If you don't want to abort it, you'll have to keep the form open by canceling the FormClosing event, then let the thread's completion callback close the form.
Check this thread for more info.
这篇关于C#中的跨线程事件处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!