Skip to content

Instantly share code, notes, and snippets.

@liorksh
Created May 1, 2020 05:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save liorksh/77229f8293ba4a9b0b00658701ca4922 to your computer and use it in GitHub Desktop.
Save liorksh/77229f8293ba4a9b0b00658701ca4922 to your computer and use it in GitHub Desktop.
Run several examples for ContinueWith, Unwrap, and async-await
[Theory]
[InlineData(456)]
public async void TasksAsyncAwait_Tests(int initialNumberOfBooks)
{
Random rnd = new Random();
LibraryAccount acc = new LibraryAccount(initialNumberOfBooks);
// Run t1, received its result (Task<int>)
Task<int> t1 = BorrowBooks(acc, nameof(t1));
// *********** First example ****************
// After completing t1, continue to another Task
int status = t1.ContinueWith<int>((prevTask) =>
{
Logger.Log($"After {nameof(t1)} execution, the books inventory is {prevTask.Result}");
// hold the execution of the thread to exemplify how the return is held
Thread.Sleep(2000);
return prevTask.Result;
}).Result;
// No need to call Wait, since Task.Result waits for the task to complete
//t1.Wait();
Logger.Log($">>> After running {nameof(t1)} and its successor: {status}");
// *********** Second example ****************
Task<int> t2 = Task.Run<Task<int>>(() =>
{
return BorrowBooks(acc, nameof(t2));
})
.Unwrap(); // return Task<int> instead of Task<Task<int>>
Task t3 = t2.ContinueWith((prevTask)=> {
Logger.Log($"After {nameof(t2)} execution, the books inventory is {prevTask.Result}");
// create another thread, without waiting for its return value.
BorrowBooks(acc, nameof(t3));
// To return from this thread only after completing the BorrowBook execution.
//BorrowBooks(acc, nameof(t3)).Wait();
});
// Waiting for t3, but the its inner thread might not be completed.
t3.Wait();
Logger.Log($">>> {nameof(t3)} completed");
// *********** Third example ****************
// Starting the task with delay
Task t4 = Task.Delay(rnd.Next(3000, 10000)).ContinueWith((p) => {
Task<int> innerTask = BorrowBooks(acc, nameof(t4));
innerTask.Wait();
});
Logger.Log($">>> Waiting for {nameof(t4)} to complete");
t4.Wait();
Logger.Log($">>> {nameof(t4)} completed");
Logger.Log($">>> The books inventory is {status}");
// *********** Forth example ****************
// Run the Task, wait until it completes, get its result.
status = await BorrowBooks(acc, "t5");
Logger.Log($">>> The library inventory after t5 is {status}");
// Calling await on t1 to fetch its result (in use-cases when it was still running in the background)
// This exemplifies the usefulness of await.
status = await t1;
Logger.Log($">>> Fetching the library inventory after t1: {status}");
// Local method: it runs a task that withdraws books from the library
Task<int> BorrowBooks(LibraryAccount account, string name)
{
return Task<int>.Run<int>(() =>
{
account.WithdrawBooksWithExecuterName(rnd.Next(1, 12), name + ":time="+DateTime.Now.Ticks);
return acc.BorrowedBooksCount;
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment