<center><h1>.Net TaskCompletionSource</h1></center>
### Introduction
The async and await keywords are widely used, but sometimes we can't know when the awaitable functions will be dismissed clearly, so that .Net provideds TaskCompletionSource to achieve that.
Also, TaskCompletionSource can be used to pause functions until the result is set, which makes multi-threaded programming easier.
### TaskCompletionSource
In awaitable functions, TaskCompletionSource plays an important role, the terminator, which aims to terminate the task and set the results:
1. Whenever SetResult() or TrySetResult() is called, the task will be ended and the reuslt will be set.
2. Call SetCanceled() or TrySetCanceled() will cancel and end the task.
3. Call SetException() or TrySetException() will end the task and throw an exception.
```csharp
public void SetResult(TResult result);
public void SetCanceled();
public void SetException(Exception exception);
public bool TrySetResult(TResult result);
public bool TrySetCanceled();
public bool TrySetException(Exception exception);
```
See? every single function that TaskCompletionSource provided is to terminate the task, cruel but useful ( ̄y▽, ̄)╭ .
### Example
Try to imagine that there has a ticket vending machine(TVM), which has two async functions, ChooseTicket() and Pay(), and is able to choose the type and amount of tickets, and the payment page should pop up and do the price calculation after all tickets are chosen.
We can achieve that goal with TaskCompletionSource easily.
```csharp
var tcs = new TaskCompletionSource<Dictionary<int, int>>();
Task.Run(async () => { await ChooseTicket(); });
Task.Run(async () => { await Pay(); });
async Task ChooseTicket()
{
Console.WriteLine("Choosing ticket type and amounts...");
Console.WriteLine("One adult ticket and three student tickets are chosen.");
Console.WriteLine("Transfering to the payment page...");
Console.WriteLine();
tcs.SetResult(new Dictionary<int, int>() {
{ 150, 3 },
{ 200, 1 },
});
}
async Task Pay()
{
var res = await tcs.Task;
var price = res.Sum(item => item.Key * item.Value);
Console.WriteLine($"Total price: {price}");
Console.WriteLine("Creadit card is chosen.");
Console.WriteLine("Successed paid, enjoy your trip.");
Console.WriteLine();
}
Console.ReadLine();
```
Result:

We can see that clearly from the example above, the Pay() function is paused until the results are set by ChooseTicket().
### References
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcompletionsource-1?view=net-6.0
https://dotblogs.com.tw/renewalwu/2014/07/27/eventdriven2awaitablemethod
https://stackoverflow.com/questions/15316613/when-should-taskcompletionsourcet-be-used
###### tags: `C#` `.Net` `Multi-thread`