Good article on BeginInvoke and Invoke differences
Here is a code template for it. On the GUI class (form or control derived object):
Here is a code template for it. On the GUI class (form or control derived object):
private delegate void DataChanged(Object Sender, BindingEventArgs Args);
private void HandleDataChanged(Object
Sender, BindingEventArgs Args)
{
// If this delegate is invoked on another thread
if (this.InvokeRequired)
{
// Asynchronously call THIS method later
// but this time on our own GUI thread
// BeginInvoke translates to a PostMessage call on
// our window.
BeginInvoke(new DataChangedDelegate(HandleDataChanged),
new object[] { Sender, Args });
}
else // when the method is invoked on the GUI thread
{ // Update our forms/controls as required
UpdateGui(Args);
}
}
Simpler form of the InvokeRequired/BeginInvoke or Invoke pattern using the MethodInvoker
private void OnHandleDataChanged()
{
// If this delegate is invoked on another thread
if (this.InvokeRequired)
{
// Asynchronously call THIS method later
// but this time on our own GUI thread
// BeginInvoke translates to a PostMessage call on
// our window.
// Invoke maps to a SendMessage call, it will BLOCK
// the calling thread until finished
BeginInvoke/Invoke(new MethodInvoker(HandleDataChanged));
}
else // when the method is invoked on the GUI thread
{
// Update our forms/controls as required
}
}
Simplest InvokeRequired Pattern, again this is within the GUI object:
// Define the delegate
private delegate void SomeDelegate(string arg1, int arg2);
// or (easier) use Action<string, int>, see below
private void HandleDataChanged(string arg1, int arg2)
{
// IF this delegate is invoked on another thread
if (this.InvokeRequired)
{ // THEN Call it again asynchronously on the GUI thread
this.BeginInvoke(
new Action<string, int>(HandleDataChanged),
// Make sure the number of args here matches the number
// of args in the delegate!
new object[] { arg1, arg2 });
return;
}
// From this point onwards we are definitely on the GUI thread again
// Update our forms/controls as required
...
}
As a rule use BeginInvoke unless Synchronization is critical when marshalling to the GUI thread. Note that BeginInvoke() in this context (marshalling to a GUI thread) is a fire and forget thing, no need to call EndInvoke() and all that shenanigans.
No comments:
Post a Comment