Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save normanlmfung/ae698ebf0f5fc8eeef762e5e57e3d057 to your computer and use it in GitHub Desktop.
Save normanlmfung/ae698ebf0f5fc8eeef762e5e57e3d057 to your computer and use it in GitHub Desktop.
csharp_tpl
using System.Threading;
using System.Threading.Tasks;
using System.Net.Http;
/*
Processor Afffinity https://stackoverflow.com/questions/2510593/how-can-i-set-processor-affinity-to-a-thread-or-a-task-in-net
ConfigureAwait - When an asynchronous method awaits a Task directly, continuation usually occurs in the same thread that created the task, depending on the async context. This behavior can be costly in terms of performance and can result in a deadlock on the UI thread. To avoid these problems, call Task.ConfigureAwait(false).
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.configureawait?view=net-8.0
What's SynchronizationContext?
https://stackoverflow.com/questions/18097471/what-does-synchronizationcontext-do
*/
class Program {
static async Task Main(string[] args)
{
var cts = new CancellationTokenSource();
var cancellationToken = cts.Token;
var parentTask = Task.Factory.StartNew(() =>
{
Console.WriteLine($"TPL 2. Thread ID (parentTask): {Thread.CurrentThread.ManagedThreadId}");
var childTask1 = Task.Factory.StartNew(() =>
{
Console.WriteLine($"TPL 3a. Thread ID (childTask1): {Thread.CurrentThread.ManagedThreadId}");
Console.WriteLine("Inside childTask1");
}, TaskCreationOptions.AttachedToParent);
var childTask2 = Task.Factory.StartNew(() =>
{
Console.WriteLine($"TPL 3b. Thread ID (childTask2): {Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000 * 3);
// throw new Exception("Bomb2");
Console.WriteLine("Inside childTask2");
}, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default); // If TaskCreationOptions.AttachedToParent, then parentTask.status will be TaskStatus.Faulted (Instead of TaskStatus.RanToCompletion)
for (int i = 0; i < 5; i++)
{
if (cancellationToken.IsCancellationRequested)
{
Console.WriteLine("Cancellation requested. Exiting loop.");
break;
}
}
}, CancellationToken.None).ContinueWith(t =>
{
Console.WriteLine($"Parent task status: {t.Status}");
if (t.Status == TaskStatus.Faulted)
{
foreach (var ex in t.Exception.Flatten().InnerExceptions)
{
Console.WriteLine($"Exception in parent task: {ex.Message}");
}
}
});
try
{
Console.WriteLine($"TPL 1. Thread ID (Main thread): {Thread.CurrentThread.ManagedThreadId}");
/*
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.configureawait?view=net-8.0
https://www.linkedin.com/pulse/should-i-use-configureawaittrue-configureawaitfalse-viswanathan/
Why after 'await', even with ConfigureAwait(true), thread id not returning to main thread?
https://stackoverflow.com/questions/78229368/dotnet-core-console-app-configureawaittrue
https://stackoverflow.com/questions/13489065/best-practice-to-call-configureawait-for-all-server-side-code
For same argument, this would why with Configure(false), we may see continuation tasks still running in new thread (not necessarily): it may still get executed in the same thread.
Essentially for dotnet core console and aspnet core/webapi's, ConfigureAwait essentially making random decision which thread to execute continuation tasks, because no synchronization context present.
*/
await parentTask.ConfigureAwait(false);
Console.WriteLine($"TPL 4. Thread ID (After ConfigureAwait): {Thread.CurrentThread.ManagedThreadId}"); // Can we use ConfigureAwait so statements after "Await" executed on same thread as parentTask, rather than main thread?
}
catch (AggregateException)
{
// Exceptions have already been handled in ContinueWith
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment