是否存在Control.BeginInvoke的变体,它在句柄被销毁之前/之后有效?

Cra*_*ney 4 .net controls asynchronous begininvoke winforms

我有一个控件,显示底层异步对象的状态.该对象引发事件,这些事件到达表单,它们基本上排队并最终使用BeginInvoke调用.

当处理控制时出现问题.因为事情是异步发生的,意味着事件回调总是可能在处理过程中排队,我有时会得到一个InvalidOperationException(在创建窗口句柄之前,不能在控件上调用Invoke或BeginInvoke).

这不是我想要的行为.我希望回调执行即使控件已被释放(即使这会导致回调中的异常;这对我来说是一个更有用的例外!).我想处理每个回调中的处理状态行为(通常只是在处理时跳过,但有时不会[例如,一个控件记录事件(可选地记录到文件)并且我不想丢失日志数据!].).

有没有一种方法可以按我想要的方式工作?我可以自己写一个不易碎的吗?

Jar*_*Par 6

试试吧SynchronizationContext.Current.这样做的PostSend构件,其大致映射到BeginInvokeInvokeControl.只要UI线程与特定控件相比,这些操作将继续运行.

该类型SynchronizationContext不是WinForms特有的,利用它的解决方案可以移植到其他框架,如WPF.

例如.

BeginInvoke代码

void OnButtonClicked() {
  DoBackgroundOperation(this); 
}

void DoBackgroundOperation(ISynchronizedInvoke invoke) {
  ThreadPool.QueueUserWorkItem(delegate { 
    ...
    delegate.BeginInovke(new MethodInvoker(this.BackgroundOperationComplete), null);
  });
}
Run Code Online (Sandbox Code Playgroud)

SynchronizationContext代码

void OnButtonClicked() {
  DoBackgroundOperation(SynchronizationContext.Current);
}

void DoBackgroundOperation(SynchronizationContext context) {
  ThreadPool.QueueUserWorkItem(delegate {
    ...
    context.Post(delegate { this.BackgroundOperationComplete() }, null);
  });
}
Run Code Online (Sandbox Code Playgroud)