问题
I have a control which displays the state of an underlying asynchronous object. The object raises events, which arrive at the form, where they are essentially queued and eventually called using BeginInvoke.
A problem arises when the control is disposed. Because things are happening asynchronously, meaning it is always possible that an event callback is queued during disposal, I sometimes get an InvalidOperationException (Invoke or BeginInvoke cannot be called on a control until the window handle has been created.).
This is not the behavior I want. I want the callback to execute even if the control has been disposed (even if that causes an exception in the callback; that's a far more useful exception to me!). I want to handle the disposed state behavior in each callback (usually just skip if disposed, but sometimes not [eg. one control logs events (optionally to a file) and I don't want to lose log data!].).
Is there a method that works the way I want? Can I write a non-brittle one myself?
回答1:
Try SynchronizationContext.Current
instead. This has the Post
and Send
members which roughly map to BeginInvoke
and Invoke
on Control
. These operations will continue to function so long as the UI thread is alive vs. a specific control.
The type SynchronizationContext
is not specific to WinForms and solutions leveraging it will be portable to other frameworks such as WPF.
For example.
BeginInvoke Code
void OnButtonClicked() {
DoBackgroundOperation(this);
}
void DoBackgroundOperation(ISynchronizedInvoke invoke) {
ThreadPool.QueueUserWorkItem(delegate {
...
delegate.BeginInovke(new MethodInvoker(this.BackgroundOperationComplete), null);
});
}
SynchronizationContext code
void OnButtonClicked() {
DoBackgroundOperation(SynchronizationContext.Current);
}
void DoBackgroundOperation(SynchronizationContext context) {
ThreadPool.QueueUserWorkItem(delegate {
...
context.Post(delegate { this.BackgroundOperationComplete() }, null);
});
}
来源:https://stackoverflow.com/questions/4513761/is-there-a-variant-of-control-begininvoke-which-works-before-after-the-handle-is