Saturday, June 25, 2011

Best tutorial of C# Async

This is by far the best tutorial of C# Async you can possibly find for the simple reason that the code is all concise and runs in the browser right in front of you!

http://www.wischik.com/lu/AsyncSilverlight/AsyncSamples.html

The examples are also quite nicely / concisely written e.g. here is a sample of a CPU intensive task made async :


public async Task AsyncResponsiveCPU()
{
    Console.WriteLine("Processing data...  Drag the window around or scroll the tree!");
    Console.WriteLine();
    int[] data = await ProcessDataAsync(GetData(), 16, 16);
    Console.WriteLine();
    Console.WriteLine("Processing complete.");
}

public Task<int[]> ProcessDataAsync(byte[] data, int width, int height)
{
    return TaskEx.Run(() =>
    {
        var result = new int[width * height];
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                Thread.Sleep(10);   // simulate processing cell [x,y]
            }
            Console.WriteLine("Processed row {0}", y);
        }

        return result;
    });
}


And heres a sample that uses the CancellationTokenSource (The CancellationToken is polled once per iteration of the y for loop to see if cancellation has been requested, and if so an OperationCanceledException is thrown.)

private CancellationTokenSource cts;

public async Task AsyncCancelSingleCPU()
{
    cts = new CancellationTokenSource();

    try
    {
        int[] data = await ProcessAsync(GetData(), 16, 16, cts.Token);
    }
    catch (OperationCanceledException)
    {
        Console.WriteLine("Processing canceled.");
    }
}

public Task<int[]> ProcessAsync(byte[] data, int width, int height, CancellationToken cancellationToken)
{
    return TaskEx.Run(() =>
    {
        var result = new int[width * height];

        for (int y = 0; y < height; y++)
        {
            cancellationToken.ThrowIfCancellationRequested();
            for (int x = 0; x < width; x++)
            {
                Thread.Sleep(10);   // simulate processing cell [x,y]
            }
            Console.WriteLine("Processed row {0}", y);
        }

        return result;
    });
}


And the best of all report progress sample

(Pings several sites, with an EventProgress object passed in to receive progres notifications.

Note that all calls into the ProgressChanged lambda are occurring while AsyncProgressPolling is suspended awaiting GetAllDirsAsync.)


private CancellationTokenSource cts;
public class GetAllPingsPartialResult
{
    public IList<string> Pings;
    public int Count;
}
public async Task AsyncProgressPolling() { cts = new CancellationTokenSource(); var progress = new EventProgress<GetAllPingsPartialResult>(); try { progress.ProgressChanged += (source, e) => { ProgressBar.Value = e.Value.Count % 100; //e is of the type GetAllPingsPartialResult }; foreach (var item in await GetAllPingsAsync(@"c:\", cts.Token, progress)) { Console.WriteLine(item); } } catch (OperationCanceledException) { Console.WriteLine("Operation canceled."); } } public async Task<string[]> GetAllPingsAsync(string root, CancellationToken cancel, IProgress progress) { var sites = new List<string>(); for (int i = 0; i < 30; i++) { sites.Add("http://www.microsoft.com"); sites.Add("http://msdn.microsoft.com"); sites.Add("http://www.xbox.com"); } var results = new List<string>(sites.Count); foreach (var site in sites) { cancel.ThrowIfCancellationRequested(); var time = DateTime.UtcNow; try {await new WebClient().DownloadStringTaskAsync(site);} catch {} var ms = (DateTime.UtcNow - time).TotalMilliseconds; results.Add(String.Format("[{0}] {1}", ms, site)); if (progress != null) progress.Report(new GetAllPingsPartialResult() { Pings = new ReadOnlyCollection<string>(results), Count = results.Count }); } return results.ToArray(); }

And if you want to read here is an excellent article : http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx

Enjoy!