4

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

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

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

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

4

1 回答 1

6

试试SynchronizationContext.Current吧。这具有大致映射到和上的PostSend成员。只要 UI 线程相对于特定控件处于活动状态,这些操作就会继续运行。BeginInvokeInvokeControl

该类型SynchronizationContext并非特定于 WinForms,利用它的解决方案将可移植到其他框架,例如 WPF。

例如。

开始调用代码

void OnButtonClicked() {
  DoBackgroundOperation(this); 
}

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

同步上下文代码

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

void DoBackgroundOperation(SynchronizationContext context) {
  ThreadPool.QueueUserWorkItem(delegate {
    ...
    context.Post(delegate { this.BackgroundOperationComplete() }, null);
  });
}
于 2010-12-22T21:16:47.333 回答