How to tell if the continuation initiated by TaskCompletionSource.TrySetResult is going to be executed synchronously or asynchronously?
For example:
I don't think there is a documented way to predict synchronous/asynchronous behaviour of SetResult
in advance. If you want to explicitly impose asynchronous continuation, the Task.Run(() => tcs.SetResult())
idea proposed by @Damien_The_Unbeliever is simple and universal.
However, if you really would like to reduce thread switching and still force asynchrony, you could wrap tcs.SetResult
with a custom dumb SynchronizationContext
. The only purpose of it would be its uniqueness as compared to the context of await tcs.Task
(and to that of any other continuations possibly registered on tcs.Task
). That would cause asynchronous continuation(s) on the consumer side of TaskCompletionSource
, either via SynchronizationContext.Post
or on a pool thread (if there's no synchronization context on the consumer side).
The test app:
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinForms_21845495
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
this.Load += async (s, e) =>
{
// test on WindowsFormsSynchronizationContext
await RequestNotificationAsync(notifyAsync: false);
Debug.WriteLine(String.Empty);
await RequestNotificationAsync(notifyAsync: true);
Debug.WriteLine(String.Empty);
// test on a pool thread
await Task.Run(() => RequestNotificationAsync(notifyAsync: false));
Debug.WriteLine(String.Empty);
await Task.Run(() => RequestNotificationAsync(notifyAsync: true));
Debug.WriteLine(String.Empty);
};
}
async Task RegisterNotification(TaskCompletionSource
The output:
B.before A.before B.after A.after B.before A.before A.after B.after B.before A.before B.after A.after B.before A.before A.after B.after