I've got an ASP.NET WebForms application which has pages using Async=True and I'm using RegisterAsyncTask(new PageAsyncTask(InitialiseAsync)); in my OnLoad method to call business logic asynchronously.
Now I know ASP.NET WebForms requires async calls to be followed with ConfigureAwait(true) as it needs to return back to the original synchronisation context to finish the page. However the async call chain goes down into a library assembly (also built by us). The library doesn't need to know, nor care about sync contexts to do its asynchronous job. Also, it could (potentially) be used in other contexts such as a Console app.
Therefore:
should the library methods always use ConfigureAwait(true) (in case it's being used by a context sensitive application such as ASP.NET Web Forms)?; or
is it okay for the library methods to use ConfigureAwait(false) and for the WebForms app to use ConfigureAwait(true)?; or
(I'm sure this is not the answer but...) should I pass in a boolean value to the library stating whether to use ConfigureAwait(true) or ConfigureAwait(false)?
I've been using option 1 up until now but I'm now suspecting that I should be using option 2 so that the library code can await back onto any thread and the app will eventually context switch back to the required context thread when the call stack comes back out.
Is that right? Thanks
ConfigureAwait is a decision that only needs to be made per function. If a specific function needs to return to its context, then it should not use ConfigureAwait(false); otherwise, it may use it. Whether the functions caller needs a context is immaterial; when its caller awaits, it can decide for itself whether to use ConfigureAwait(false) or not. So option (3) should never be used.
You can go with option (2), and that's the one that I would choose at this time. ConfigureAwait(false) does have some benefits. However, there is currently an ongoing shift in opinion on this matter, largely driven by the fact that ASP.NET Core does not have a context (so ConfigureAwait(false) is a noop, and people don't like it cluttering up their code). For myself, I still use ConfigureAwait(false) in library code, but some other developers have removed ConfigureAwait(false) from their libraries completely. This is equivalent to your option (1). Either of those options would work; if performance isn't a concern, it just comes down to preference.
Related
I've imported Microsoft.VisualStudio.Threading into .Net Core Web App. I did this specifically to make use of AsyncLazy<T>.
I wanted to make sure I did this right, so I imported the appropriate Analyzers.
The warnings and the documentation clearly state that a JoinableTaskFactory should be injected into my implementation.
My question is, how should I instantiate that JoinableTaskFactory in the configuration of my .Net Core Web App?
Is it as simple as
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddSingleton(new JoinableTaskFactory());
// ...
}
or, is that all wrong?
Yes, you can use the Microsoft.VisualStudio.Threading library in ASP.NET Core applications. But while JoinableTaskFactory would "work" in such an app, it's a pretty good sign you're doing something wrong.
The analyzers are always appropriate of course, and the warnings you saw were perhaps pointing out that you shouldn't call Task.Result, Task.Wait(), etc. These synchronously block threads and can severely reduce the scalability of your web app (or any app for that matter). You should use await instead wherever possible.
JoinableTaskFactory is there to step in when you can't use await but you still need to call async code. Using JTF.Run will still block the calling thread, but it will do so in a way that avoids deadlocks when you have a single threaded SynchronizationContext in the application. I don't think ASP.NET Core has such a thing, so that's not a concern. JTF.Run is still more efficient than Task.Wait since it can reuse the original thread for continuations instead of a second thread.
If you do choose to use JTF in your web app, if ASP.NET Core doesn't use a single-threaded SynchronizationContext then you can create and share a single JTF instance with the entire app. But if it does have a single-threaded SynchronizationContext, it will be one per web request, which means you need to create a new JoinableTaskContext for each request since these are affinitized to one SynchronizationContext. You always get your JTF instance from a JoinableTaskContext instance.
This page of the vs-threading docs says
The ThreadHelper.JoinableTaskFactory property only works for code running in the VS process. If your code is running out of proc (in the vstest.executionengine.exe runner for instance) it won't work.
So, as the name of the package, Microsoft.VisualStudio.Threading, suggests, it's intended to be used for Visual Studio extensions. The code that you linked for its implementation of AsyncLazy uses JoinableTaskFactory, so it's probably not suitable outside of Visual Studio. I certainly would never use it outside of a VS extension that needs to switch to the UI thread.
Steven Cleary's AsyncEx library has an AsyncLazy, and the wiki page links to this Steven Toub blog post titled AsyncLazy. The blog post points out that the lazy semantics doesn't really add much over what Task<T> provides, although since the value factory might do a lot of work before reaching an await his sample runs it on the thread pool and unwraps the Task<Task<T>>.
edit: As pointed out in the comments, my quote from the docs is somewhat out of context. However, the vs-threading library is about avoiding deadlocks when using async with a synchronisation context (primarily a GUI). ASP.NET Core, what the author of the question is using, does not have a synchronisation context, hence doesn't need to worry about deadlocking the main thread specifically. While using the vs-threading library probably won't cause problems, as my quote claimed, I still don't think it's a good fit for anything without a synchronisation context and there are much better alternatives, like using Task<T> directly and not need any AsyncLazy implementation.
When await is encountered by the compiler it transforms the async method to a state machine and the continuation is scheduled via
AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted as outlined here or AsyncTaskMethodBuilder.AwaitOnCompleted as outlined here.
Looking through .NET source here,
AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted calls Awaiter.UnSafeOnCompleted
It appears that Awaiter.UnSafeOnCompleted does not flow the ExecutionContext (code here).
Notice it passes false to flowExecutionContext. This means if I am using LogicalCallContext (part of ExecutionContext) to store any data (e.g. activityId) then it wont be flowed in continuation path which means I cannot access it.
So, my question is what causes the compiler to choose Unsafe Completion ?
Stephen Toub also mentioned the same thing here but did not give any details.
"All of the methods in the .NET Framework that fork asynchronous work capture and restore ExecutionContext in a manner like this (that is, all except for those prefixed with the word “Unsafe,” which are unsafe because they explicitly do not flow ExecutionContext"
This means if I am using LogicalCallContext [...] to store any data [...] then it wont be flowed in continuation path
Not exactly. OnCompleted is just one of the possible ways for the execution context to flow. You'd need to rule out the other ways in which it may flow.
So, my question is what causes the compiler to choose Unsafe Completion ?
The compiler will use this whenever possible (i.e. whenever ICriticalNotifyCompletion is implemented).
However, the compiler also relies indirectly on AsyncMethodBuilderCore, and this does cause the execution context to flow, through its MoveNextRunner helper class. This manages to do it, in this case, more efficiently, by only storing a single reference to the execution context, rather than one reference for each continuation.
Unless you're going out of your way to prevent the execution context from flowing, you shouldn't need to worry about it.
I am using Windows Azure with the WebJobsSDK and I was wondering if, when calling aync methods, I should add ConfigureAwait(false) to the awaited calls. In other words, does the SDK require the async methods to return to the original context to continue to function properly?
does the SDK require the async methods to return to the original context to continue to function properly?
I don't know the answer to this question; it may depend on the host. That is, the SDK itself won't require a particular context, but the host might.
However, I'd say it doesn't matter. Considering this question:
Should I use ConfigureAwait(false) in the top level call of Azure WebJobsSDK
If the context is required, then the host will provide a context, and you shouldn't use ConfigureAwait(false).
If there is no context, then the host will not provide a context, and it won't matter whether you use ConfigureAwait(false) or not.
If there is a context provided but it's not required, then using ConfigureAwait(false) will reduce your overhead by a tiny, tiny amount - not something to lose sleep over.
So, I'd say that capturing the context (i.e., not using ConfigureAwait(false)) is the safest solution across any host.
Using async/await as shown here http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html, one of the good practices is using ConfigureAwait(false) so the method return does not have to come back to the request context. What are the potential consequences of using this? Asked another way, when would this not be recommended?
when would this not be recommended?
Your method must return to the same context if there's code further down in the method that depends on that context. If the remainder of that method does not require a particular context, then it's a good practice to use ConfigureAwait(false).
There are two primary examples: UI code and ASP.NET code.
UI code must run on the UI thread; this includes most UI widget access, and I extend the definition of "UI code" to include my ViewModels as well (there are some situations in WPF where you can get away with updating the UI from a background thread, but that's not true for all MVVM platforms). So, if your method ends with a textBox1.Text = "" or a myViewModel.MyObservableCollection.Add(4), then it has to return to the UI thread before it can execute that code.
ASP.NET code must run in an ASP.NET request context; this includes any code that depends on HttpContext.Current (and many System.Web APIs implicitly assume an ASP.NET request context). So, if your method ends with HttpContext.Current.Items..., then it has to return to the ASP.NET request context before it can execute that code. (Side note: in ASP.NET vNext on .NET 4.6 and higher, the ASP.NET request context is actually going away).
In practice, what this means is that most library code should use ConfigureAwait(false), since well-written library code does not have a dependency on a particular UI framework or System.Web. Similarly, most application code should not use ConfigureAwait(false), since it has to update the UI / send an HTTP response.
I'm working on a WPF application with heavy multi-threading using a bit of async/await. I'm pondering the use of Unit of Work pattern (with implicit scoping) within the client (having it work much like a TransactionScope), but can't decide where to store the context.
Some things I've considered:
Thread locals; but that won't work as we may switch threads in a nested unit of work.
Static; I believe this will fail if two unrelated unit of works are executed at the same time
In my service layer (webapi odata), I attach the unit of work to the http context to allow nesting across threads. Has anyone tried something like this in a client app and have a decent way of scoping nested units of work?
Unit of Work doesn't necessarily mean that the context is implicit (or scoped, for that matter). I believe it's quite normal for UoW to be explicit (e.g., your BO types would keep a reference to their "owning" context, which is itself threadsafe). That said, an implicit context is possible with async.
When you use await only in an ASP.NET request context, the best option is to use HttpContext.Items. Alternatively, you could use threadsafe static members.
When you use await only in a UI context, you could use regular static members.
When you use multithreading, you could use thread locals.
However, if any of your code uses multithreading with await (e.g., ConfigureAwait(false), or passing an async lambda to Task.Run), then none of those options will work.
AFAIK, there is only one general solution, which I describe on my blog: CallContext.LogicalGetData and CallContext.LogicalSetData. The logical call context will flow across threads and would work in any async situation.
There are some limitations to this approach:
You must use the .NET 4.5 framework. CallContext was made async-aware in .NET 4.5, so if you're targeting .NET 4.0 / Phone / Silverlight, this won't work correctly.
You should only store immutable data. This is made much easier if you use Microsoft.Bcl.Immutable.