.

Thread.Sleep vs async Task.Delay

Rather use Task.Delay, since it’s not blocking.

private async void button1_Click(object sender, EventArgs e)
{
    // Call the method that runs asynchronously.
    string result = await WaitAsynchronouslyAsync();

    // Call the method that runs synchronously.
    //string result = await WaitSynchronously ();

    // Display the result.
    textBox1.Text += result;
}

// The following method runs asynchronously. The UI thread is not
// blocked during the delay. You can move or resize the Form1 window 
// while Task.Delay is running.
public async Task<string> WaitAsynchronouslyAsync()
{
    await Task.Delay(10000);
    return "Finished";
}

// The following method runs synchronously, despite the use of async.
// You cannot move or resize the Form1 window while Thread.Sleep
// is running because the UI thread is blocked.
public async Task<string> WaitSynchronously()
{
    // Add a using directive for System.Threading.
    Thread.Sleep(10000);
    return "Finished";
}

Threading in C#

Delaying without blocking:
Thread.Sleep is a synchronous delay. If you want an asynchronous delay then use Task.Delay.

// Execution of the async method will continue one second later, but without blocking.
await Task.Delay(1000);

Task.Run vs Task.Factory.StartNew

 

Working with scheduled tasks:

TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext();
var task = Task.Factory.StartNew(() =>
                                     {
                                         //do some work here
                                     },
                                 CancellationToken.None,
                                 TaskCreationOptions.None,
                                 ui);

task.ContinueWith(t => Thread.Sleep(1000), TaskScheduler.Default)
    .ContinueWith(t =>
                      {
                          //do more work here
                      }, ui);

Starting a Async task from a non-async method … such as static void Main():

private static void Main(string[] args)
{
	var myTask = GetIt();
	Task.WaitAll(myTask);
	List<Instrument> result = myTask.Result;
}
private static async Task<List<Instrument>> GetIt()
{
	return await Task.Delay(10000); // DoSomeAsyncWorkHere...
}

Parallel code execution

Example of executing code in parallel:

public void FetchEXAMPLE()
{
    var service = new service();
    Task.WaitAll(
        new[]
            {
                Task.Factory.StartNew(
                    () => { AdUsers = service.GetADUsers(); }),
                Task.Factory.StartNew(
                    () =>
                        {
                            Staffs = service.GetUnlinkedStaff();
                            StaffTypes = service.GetAllStaffTypes();
                        })
            });
}

Cross-thread operation not valid

Trying to update a control from another thread will throw an error similar to below:
Cross-thread operation not valid: Control ‘BusyForm’ accessed from a thread other than the thread it was created on.
The solution to this is to wrap your code in a thread-safe wrapper (see method ThreadSafe_Close) as follow:

public partial class BusyForm : Form
{
    public BusyForm()
    {
        InitializeComponent();
    }

    public void ThreadSafe_Close()
    {
        if (InvokeRequired)
        {
            Invoke(new Action(ThreadSafe_Close));
            return;
        }

        Close();
    }
}

void Main()
{
    BusyForm b = new BusyForm();
    b.Show();
    Action<string> AsyncMethod = (input) => 
            { Thread.Sleep(2000); };
    AsyncMethod.BeginInvoke("Input", (asyncResult) =>
        {
            //OLD CODE: b.Close(); throws an error!! 
            b.ThreadSafe_Close();
        }, AsyncMethod);
}

asynchronous callback threading in c#

The long way:

static void Main()
{
  Func<string, int> method = TheWorkMethod;
  method.BeginInvoke ("test", Completed, method);
}

static int TheWorkMethod (string s) { return s.Length; }

static void Completed (IAsyncResult res)
{
  var target = (Func<string, int>) res.AsyncState;
  int result = target.EndInvoke (res);
  Console.WriteLine ("String length is: " + result);
}

For a function such as int DoFunction(string S):

Func<string, int> AsyncFunction = (input) =>
        {
          MessageBox.Show("Start " + input); 
          Thread.Sleep(5000); 
          return 5;
        };
AsyncFunction.BeginInvoke("InputText", funcResult =>
        {
            MessageBox.Show("Completed: result="+funcResult);
        }, 
        AsyncFunction);

For a method such as void DoMethod(string S):

Action<string> AsyncMethod = (input) => 
        { 
            MessageBox.Show("Start " + input); 
            Thread.Sleep(5000); 
        };
AsyncMethod.BeginInvoke("InputText", (asyncResult) => 
        { 
            MessageBox.Show("Completed: "+asyncResult.IsCompleted);
        }, 
        AsyncMethod);

DoEvents

System.Windows.Forms.Application.DoEvents();

threading – parameterized

lambda: Thread thread = new Thread(() => download(filename));

c# 2.0 Thread thread = New Thread(delegate() { download(filename); });

long way:
var thread = new Thread(new ParameterizedThreadStart(download));

others:

 ThreadPool.QueueUserWorkItem( () => value = Process(value)); // use captured variable

 
// -- OR --

 
ThreadPool.QueueUserWorkItem( () =>
     
{
           
double val = value;      // use explicit parameter
           val
= Process(val);      // v is not changed
     
});

 
// -- OR --

 
ThreadPool.QueueUserWorkItem( (v) =>
     
{
           
double val = (double)v;  // explicit var for casting
           val
= Process(val);      // v is not changed
     
}, value);



BOOKS!

threading invokeRequired invoke

The following is a demonstration of how the invokeRequired can be used in Threading:

public partial class Form1 : Form
    {
        private System.Windows.Forms.TreeView treeView1;
 
        public Form1()
        {
            this.treeView1 = new System.Windows.Forms.TreeView();
        }
        Microsoft.Win32.RegistryKey[] allkeys = new Microsoft.Win32.RegistryKey[]
        {
            Microsoft.Win32.Registry.ClassesRoot,
            Microsoft.Win32.Registry.CurrentConfig,
            Microsoft.Win32.Registry.CurrentUser,
            Microsoft.Win32.Registry.DynData,
            Microsoft.Win32.Registry.LocalMachine,
            Microsoft.Win32.Registry.PerformanceData,
            Microsoft.Win32.Registry.Users
        };
 
 
        private void RefreshRegistryListView()
        {
            if (treeView1.InvokeRequired)
            {
                treeView1.Invoke(new MethodInvoker(RefreshRegistryListView));
                return;
            }
            else
                UpdateTheTreeview(this, null);
        }
 
        private void UpdateTheTreeview(object Sender, EventArgs e)
        {
            TreeNode TN = new TreeNode();
            Dictionary<string, TreeNode> RegistryNodes = new Dictionary<string,TreeNode>();
            foreach (Microsoft.Win32.RegistryKey key in allkeys)
            {
                TreeNode T = TN.Nodes.Add(key.Name);
                RegistryNodes.Add(key.Name, T);
            }
            foreach (Microsoft.Win32.RegistryKey key in allkeys)
            {
                Application.DoEvents();
                try
                {
                    foreach (string s in key.GetSubKeyNames())
                        RegistryNodes[key.Name].Nodes.Add(s);
                }
                catch { }
            }
            treeView1.Nodes.Clear();
            foreach (TreeNode key in RegistryNodes.Values)
                treeView1.Nodes.Add(key);
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            Thread oThread = new Thread(new ThreadStart(RefreshRegistryListView));
            oThread.Start();
        }
    }