Best Way to Invoke Any Cross-Threaded Code?
I know that this question has been asked before, but I'm looking for a way to:
- streamline the creation of safe cross-threaded code.
- reuse this code in any situation (no Windows Forms references).
Here's what I have so far, but I want to remove the Windows Forms references. Any ideas?
public delegate void SafeInvokeDelegate(System.Action action);
public class SafeInvoke
{
private readonly System.Windows.Forms.Control _threadControl;
public SafeInvoke()
{
_threadControl = new System.Windows.Forms.Control();
}
public void Invoke(System.Action action)
{
if (_threadControl.InvokeRequired)
_threadControl.Invoke(new SafeInvokeDelegate(Invoke), new object[] {action});
else if (action != null) action();
}
}
The above class might be used this way:
SafeInvoke _safeInvoker = new SafeInvoke();
void SafeClearItems()
{
_safeInvoker.Invoke(delegate
{
listView1.Items.Clear();
});
}
How would I remove the System.Windows.Forms.Control in the SafeInvoke class but keep the same functionality?
You also could use an extension method and lambdas to make your code much cleaner.
using System.ComponentModel;
public static class ISynchronizeInvokeExtensions
{
public static void InvokeEx<T>(this T @this, Action<T> action) where T : ISynchronizeInvoke
{
if (@this.InvokeRequired)
{
@this.Invoke(action, new object[] { @this });
}
else
{
action(@this);
}
}
}
So now you can use InvokeEx
on any ISynchronizeInvoke and be able to access the properties and fields of implementing class.
this.InvokeEx(f => f.listView1.Items.Clear());
Use ISynchronizeInvoke
instead of Control
. That's the interface that Control
implements with Invoke/BeginInvoke/EndInvoke/InvokeRequired
.
An alternative is to use SynchronizationContext.Current
- which is what BackgroundWorker
uses, I believe.