我有一个控件,显示底层异步对象的状态。该对象引发事件,这些事件到达表单,它们基本上排队并最终使用BeginInvoke调用。
控制处理时出现问题。因为事情是异步发生的,这意味着事件回调在处理过程中总是可能排队,我有时会得到一个InvalidOperationException(在创建窗口句柄之前,不能在控件上调用Invoke或BeginInvoke。)。
这不是我想要的行为。我希望回调执行即使控件已被释放(即使这会导致回调中的异常;这对我来说是一个更有用的例外!)。我想在每个回调中处理已处置的状态行为(通常只是在处理时跳过,但有时不会[例如,一个控件记录事件(可选地记录到文件)并且我不想丢失日志数据!]。 / p>
有没有一种方法可以按我想要的方式工作?我可以自己写一个非脆弱的吗?
答案 0 :(得分:6)
请尝试使用SynchronizationContext.Current
。这有Post
和Send
成员大致映射到BeginInvoke
和Invoke
Control
。只要UI线程与特定控件相比,这些操作将继续运行。
类型SynchronizationContext
并非特定于WinForms,利用它的解决方案可以移植到其他框架,如WPF。
例如。
BeginInvoke Code
void OnButtonClicked() {
DoBackgroundOperation(this);
}
void DoBackgroundOperation(ISynchronizedInvoke invoke) {
ThreadPool.QueueUserWorkItem(delegate {
...
delegate.BeginInovke(new MethodInvoker(this.BackgroundOperationComplete), null);
});
}
SynchronizationContext代码
void OnButtonClicked() {
DoBackgroundOperation(SynchronizationContext.Current);
}
void DoBackgroundOperation(SynchronizationContext context) {
ThreadPool.QueueUserWorkItem(delegate {
...
context.Post(delegate { this.BackgroundOperationComplete() }, null);
});
}