static void

.Net Threading

Simple Threads

Thread t = new Thread(SlowMethod); //ThreadStart delegate (no parameters)
t.Start(); //start it
t.Join(); //wait for it to finish
Debug.WriteLine(Thread.CurrentThread.Name + " Child threads finished");

//ParameterizedThreadStart delegate (one "object" parameter)
Thread tp = new Thread(SlowMethodWithObjectParameter);
tp.Start(1000); //pass in object start
tp.Join();

//Strongly typed with a delegate
Thread td = new Thread(delegate() { SlowMethodWithParameter(2000); });
td.Start(); //start the delegate which starts the method
td.Join();

ThreadPool

//optimize with ThreadPool (WaitCallback must have one "object" parameter)
ThreadPool.QueueUserWorkItem(SlowMethodWithObjectParameter);

Async delegates

//simple async delegate
//private delegate string WorkerDelegate(string s);
//private string Worker(string s) { return s.ToUpper(); }
WorkerDelegate method = Worker;
IAsyncResult ar = method.BeginInvoke("test", null, null);
// do other stuff
string uppercased = method.EndInvoke(ar);
// ** or **
method.BeginInvoke("test", DoneCallback, null);
/*static void DoneCallback(IAsyncResult ar)
{Debug.WriteLine(((WorkerDelegate)ar.AsyncState).EndInvoke(ar));}*/

Threading notes

Timers

System.Threading.Timer tm = new System.Threading.Timer(new TimerCallback(Tick), "tock", 0, 0);
//startTime - 0 to start immediately, period- 0 to execute once
 
System.Timers.Timer tm2 = new System.Timers.Timer(1000);
tm2.Elapsed += delegate { Debug.WriteLine("Tock"); };
tm2.Enabled = true;
//do something
tm2.Enabled = false; //stop it
 
//remember System.Windows.Forms.Timer only works in WinForms and is actually singlethreaded

Thread Sync

msdn

Asynchronous Patterns

All delegates automatically have xInvoke methods (webservices, IO and ADO has BeginX/EndX where X is the method call)

The async patterns are wait (waithandle or EndInvoke), polling (IsCompleted) and Callback

protected void Main()
{
    Literal1.Text = "Load= " + Thread.CurrentThread.ManagedThreadId;
    Literal2.Text = "Begin/End= " + TestAsync();
    Literal3.Text = "Load= " + Thread.CurrentThread.ManagedThreadId;
    Literal4.Text = "Polling= " + TestAsyncPolling();
    Literal5.Text = "Load= " + Thread.CurrentThread.ManagedThreadId;
    Literal6.Text = "WaitHandle= " + TestAsyncWaitHandle();
    TestAsyncCallback();
    Literal7.Text = "Callback= " + _result;
    Literal8.Text = "Load= " + Thread.CurrentThread.ManagedThreadId;
}
 
//a normal method doing something slow
public int SlowMethod(int sleep)
{
    Thread.Sleep(sleep);
    return Thread.CurrentThread.ManagedThreadId;
}
 
//delegate with same signature
public delegate int SlowMethodDelegate(int sleep);
 
public int TestAsync()
{
    SlowMethodDelegate dg = SlowMethod; //create delegate
    IAsyncResult ar = dg.BeginInvoke(2000, null, null); //start
    Thread.Sleep(1000); //possibly do other work
    return dg.EndInvoke(ar); //block until done
}
 
public int TestAsyncPolling()
{
    SlowMethodDelegate dg = SlowMethod; //create delegate
    IAsyncResult ar = dg.BeginInvoke(2000, null, null); //start
    while (!ar.IsCompleted)
    {
        Thread.Sleep(500); //possibly do other work
    }
    return dg.EndInvoke(ar);
}
 
public int TestAsyncWaitHandle()
{
    SlowMethodDelegate dg = SlowMethod; //create delegate
    IAsyncResult ar = dg.BeginInvoke(2000, null, null); //start
    Thread.Sleep(500); //possibly do other work
    ar.AsyncWaitHandle.WaitOne(); //block until done
    return dg.EndInvoke(ar);
}
 
private int _result;
public void TestAsyncCallback()
{
    SlowMethodDelegate dg = SlowMethod; //create delegate
    IAsyncResult ar = dg.BeginInvoke(2000, CallBack, dg); //start
    //end
}
private void CallBack(IAsyncResult ar)
{
    SlowMethodDelegate dg = (SlowMethodDelegate) ar.AsyncState; //our delegate back
    _result = dg.EndInvoke(ar);
}

.Net 4.0 Task Parallel Library

//separate creation from scheduling
//var task1 = new Task<int>(() => int.MaxValue);
//task1.Start();
//preferred
var task = Task.Factory.StartNew(() => int.MaxValue);
 
try
{
    //block with a timeout
    if (!task.Wait(TimeSpan.FromSeconds(1)))
    {
        Debug.WriteLine("It took longer than a second");
    }
    return task.Result;
}
catch (AggregateException exception)
{
    // exception.InnerExceptions can include nested AggregateExceptions
    // so exception.Flatten() to simplify
    exception.Handle(x =>
                         {
                             if (x is OverflowException)
                             {
                                 Console.WriteLine("Overflow handled");
                                 return true;
                             }
                             return false;
                         });
}

Multiple tasks

var tasks = new Task[2]
{
    Task.Factory.StartNew(Work1),
    Task.Factory.StartNew(Work2)
};
 
//Block until all tasks complete.
Task.WaitAll(tasks);

Continuations

var continuationTask = Task.Factory
    .StartNew(() => ReadFile())
    .ContinueWith(x => ReadLines(x.Result));

Also ContinueWhenAll, ContinueWhenAny

Cancellations

MSDN. Pass in a cancellation token and cancel the token source on the main thread.

var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var task = Task.Factory.StartNew(() =>
{
    token.ThrowIfCancellationRequested();
    for (var i = 0; i < 3; i++)
    {
        Thread.Sleep(TimeSpan.FromSeconds(1));
        //raise an OperationCanceledException
        if (token.IsCancellationRequested)
            token.ThrowIfCancellationRequested();
    }
    //pass in the token
}, token);
//cancel it
tokenSource.Cancel();
//run it
try
{
    task.Wait();
}
catch (AggregateException)
{
    //will hit here
}
Console.WriteLine(task.IsCanceled);