If the task-like types of your library does not capture the context when awaited, then the users of your library will not be able to do this:
private async void Button_Click(object sender, EventArgs e)
{
string input = Textbox1.Text;
TaskLike<string> taskLike = YourLibrary.ProcessAsync(input);
string result = await taskLike;
Label1.Text = result // InvalidOperationException: Cross-thread operation not valid
}
On the other hand if the task-like types of your library always capture the synchronization context when awaited, then your library will be inefficient as a building block of other libraries, and will require from the other libraries authors to jump through hoops in order to invoke your library in a synchronization-context-free manner. So making your task-like types configurable regarding capturing the synchronization context should be a desirable feature.
Regarding whether you should use ConfigureAwait(false)
when the internal code of your library encounters standard Task
s, it depends on whether your library accepts caller-supplied lambdas. If for example your library includes a method like this:
public TaskLike<string> ProcessAsync(Action action);
...then invoking the action
after awaiting internally something with ConfigureAwait(false)
may result to cross-thread violation exceptions, if the caller's lambda includes thread-affine code like reading properties of UI controls. To solve this problem may require to introduce a configuration parameter continueOnCapturedContext
in the method's signature. At least this is the solution chosen by the Polly library.