a method can return a Task. it is common to suffix these with Async.
public Task DoSomthingAsync()
{
return Task.Run(() => Thread.Sleep(30000));
}
the calling thread can wait for its completion.
DoSomthingAsync().Wait();
DoSomethingElse();
return;
this blocks the current thread until the async thread completes. that is DoSomethingElse will not run until DoSomthingAsync() completes.
but what if you did not want to block the main the thread, but still wanted DoSomethingElse() to run after DoSomthingAsync() completes. Then you use the Task.ContinueWith,
DoSomthingAsync()
.ContinueWith(() => DoSomethingElse());
return;
now the return will happen before the Task runs, and the DoSomethingElse() will run after DoSomethingElse
to overlap another call its:
DoSomthingAsync();
.ContinueWith(() => DoSomethingElse());
DoYetAnotherThingSync();
return;
here DoYetAnotherThingSync() will run on the main thread, while other work is done on a Task pool thread. the return will happen after DoYetAnotherThing() completes (but DoSomthingAsync() may still be running).
if it was DoYetAnotherThingAsync(), two task thread would run and the return would happen before they completed,
you can also overlap and block
var task = DoSomthingAsync();
DoYetAnotherThingSync();
task.Wait(); // block thread to task completes
return;
as chaining become tedious and harder to read, especially if the ContinueWith is code rather than a single call
DoSomthingAsync()
.ContinueWith(() => DoSomethingElse1())
.ContinueWith(() => DoSomethingElse2())
.ContinueWith(() => DoSomethingElse3())
.ContinueWith(() => DoSomethingElse4());
return;
c# added await keyword. The compiler just converts the code after the await to ContimeuWith()
var i=0;
await Task1();
i++;
await Task2();
i++;
await Task3();
i++;
return i;
becomes:
var i=0;
Task1().ContinueWith(() =>
{
i++;
return Task2().ContinueWith(() =>
{
i++;
return Task3().ContinueWith(() =>
{
i++;
return i;
})
})
});
as you can see the former is easier to read. for a method to use await(), it must return a Task and be prefixed with async:
async Task<int> DoWorkAsync()
{
await Task1();
await Task2();
}
now the call of DoWork(), has a couple options
DoWorkAsync(); // fire and forget
await DoWorkAsync(); // free thread while waiting (requires method returns task)
DoWorkAsync().Wait();// block thread until complete
note: one issue with UI and threads, is often the UI components can only be updated from the UI thread. in this the UI provides a way to execute code on the UI thread from another thread.