Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best Way to Invoke Any Cross-Threaded Code?

Tags:

c#

.net

invoke

I know that this question has been asked before, but I'm looking for a way to:

  1. streamline the creation of safe cross-threaded code.
  2. 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?

like image 845
CLaRGe Avatar asked Apr 02 '09 20:04

CLaRGe


2 Answers

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()); 
like image 134
Samuel Avatar answered Oct 05 '22 01:10

Samuel


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.

like image 30
Jon Skeet Avatar answered Oct 05 '22 03:10

Jon Skeet