1. Task
2. async - await
- Run async, return a value and wait
- Run async, return a value and do NOT wait
- Worker method without await
- Does not run async even if marked as async and called with await
3. Calling asynchronously a method that is not marked with async from an async
4. Updating UI from methods executed on another thread
5. Canceling running task
This article describes Task class and async - await concept. Available in Visual Studio 2012 and newer. Code examples
1. Task
Basically, Task is class that represents a task running on (typically) another (worker) thread. Create task
C# private void LongTaskNoParam() { // do something here } Task task1 = new Task(LongTaskNoParam); task1.Start();Create task with factory
C# Task task2 = Task.Factory.StartNew(LongTaskNoParam);Passing parameter to the task
C# private void LongTaskParam(object myParam) { // do something here } Task task3 = Task.Factory.StartNew(LongTaskParam, 3000);Waiting for the task.
UI will be blocked if you wait in the same method.
Note: You can limit execution by timeout or pass cancellation token.
C# task3.Wait();Running task on the same thread.
Be aware that you can start one task only once.
C# Task task4 = new Task(LongTaskNoParam); task4.RunSynchronously();
2. async - await
In order to execute a method asynchronously:
1. The method has to be marked with async
2. Return type must be Task<>
3. If the caller needs to wait until async call finishes, use await
4. await can be used only inside a method marked as async
5. In order to run asynchronously, the method marked as async has to call another async method or Task.Run
6. async methods cannot have out or ref parameters
MSDN
Asynchronous Programming with Async and Await
Control flow in async programs
await
Run async, return a value and wait
C# public async Task<string> RunsAsynchronously(int sleepTime) { Log("1"); await Task.Delay(sleepTime); Log("2"); // start + sleep time return " Finished Async"; } private async void button1_Click(object sender, EventArgs e) { string s = await RunsAsynchronously(3000); Log("3"); // start + sleep time }
Run async, return a value and do NOT wait
C# public async Task<string> RunsAsynchronously(int sleepTime) { Log("2"); await Task.Delay(sleepTime); Log("3"); return " Finished Async"; } private async void button1_Click(object sender, EventArgs e) { RunsAsynchronously(3000); // cannot assign result "string s = " without "await" Log("1"); // start RunsAsynchronously() and continues }
Worker method without await
C# public async Task<string> RunsAsynchronously(int sleepTime) { Log("1"); Task.Delay(sleepTime); // will not wait here without "await" Log("2"); // Log("1") + 0.01sec return " Finished Async"; } private async void button1_Click(object sender, EventArgs e) { string s = await RunsAsynchronously(3000); Log("3"); // Log("2") + 0.01s time }
Does not run async even if marked as async and called with await
C# public async Task<string> WillNotRunAsync() { Thread.Sleep(2000); // simulates long running method return "Did not run async"; } Task<string> result = await WillNotRunAsync();because WillNotRunAsync does not call another async method.
3. Calling asynchronously a method that is not marked with async from an async
C# private string LongTaskWithResult() { Thread.Sleep(5000); return "LongTaskWithResult"; } private async Task<string> LongTaskWithResultAsync() { string s = await Task.Factory.StartNew(() => LongTaskWithResult()); return s; } ... string s = await LongTaskWithResultAsync();or call it directly, if the caller is marked as async
C# string s = await Task.Factory.StartNew(() => LongTaskWithResult());In both cases, the caller has to be a method marked with async.
In order to call a non async method from another non async method, you need to mark the anonymous method as async
C# string s; Task.Factory.StartNew(async () => { s = await LongTaskWithResultAsync(); // here the code waits DoSomething(); }); // here the code does NOT wait
4. Updating UI from methods executed on another thread
C# using System.Threading; .... SynchronizationContext m_syncContext; SendOrPostCallback m_UIUpdateMethod; public MyForm() { m_syncContext = SynchronizationContext.Current; // stores main thread context m_UIUpdateMethod = UIUpdateMethod; } private void UIUpdateMethod(object state) { textBox1.Text += (string)state; } public async Task MyAsynchronousMethod() { m_syncContext.Post(m_UIUpdateMethod, "Hello from MyAsynchronousMethod()"); }
5. Canceling running task
C# private void LongTask(CancellationToken ct) { for (int i=0; i < 100; i++) { if (ct.IsCancellationRequested) { return; } else { // Do something } } } CancellationTokenSource cts = new CancellationTokenSource(); CancellationToken ct = cts.Token; Task.Factory.StartNew(() => LongTask(ct), ct); ... cts.Cancel(); // cancel when needed