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.
Related
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.
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.
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 have a C# webserver which I have been profiling using the StackOverflow miniprofiler. Because it's not an ASP.NET server, but each request was typically executed on its own thread, I rigged the miniprofiler to use ThreadStatic storage to track all of the profilers of an incoming request from start to finish. This worked well.
Recently we've converted everything to use async/await, which means continuations after an await typically don't come back onto the same Thread and thus the ThreadStatic storage no longer works.
What's the best way to pass some small piece of data between different ThreadPool threads in this case? Are there existing SynchronizationContext implementations that would be useful for something like this?
What's the best way to pass some small piece of data between different ThreadPool threads in this case?
Using the logical call context via the CallContext class. It exposes two static methods: LogicalSetData and LogicalGetData. The call context is stored and marshaled via the ExecutionContext, which is also in charge of the sync context, etc.
Using this class has two restrictions:
You're limited to the use of .NET 4.5 and above
Logical call context uses copy-on-write semantics, and performs a shallow copy once the data is mutated. This means you should only be using immutable data, as the references may be shared across multiple threads.
One last thing to note is CallContext is initialized only once you call it. This means that when using it, you're taking on some overhead because of the copy-on-write.
More on that can be found in a post by Stephan Cleary called Implicit Async Context
Is it possible to define and call method asynchronously in the same thread as the caller?
Suppose I have just one core and I don't want threading management overhead with like 100 threads.
Edit
The reason I ask is nodejs model of doing things - everything on one thread never blocking anything, which proved to be very efficient, which made me wonder if same stuff possible in C# (and I couldn't achieve it myself).
Edit2 Well, as noted in comments node isn't single-threaded after all (however simple load test shows, that it uses just one core...), but I think what makes it so efficient is implicit requirement to write only non-blocking code. Which is possible in C#, except not required:) Anyway, thanks everyone...
More info in
this SO post and even more in this one
It's not really clear exactly what context you're talking about, but the async/await feature of C# 5 already helps to support this sort of thing. The difference is that whereas in node.js everything is forced to be single threaded by default (as I understand it; quite possibly incorrectly given the links in the comments), server-side applications in .NET using asynchrony will use very few threads without limiting themselves to that. If everything really can be served by a single thread, it may well be - if you never have more than one thing to do in terms of physical processing, then that's fine.
But what if one request comes in while another is doing a bit of work? Maybe it's doing just a small amount of encryption, or something like that. Do you really want to make the second request wait for the first one to complete? If you do, you could model that in .NET fairly easily with a TaskScheduler associated with a single-thread thread-pool... but more commonly, you'd use the thread-pool built into .NET, which will work efficiently while still allowing concurrency.
First off, you should make sure you're using .NET 4.5 - it has far more asynchronous APIs (e.g. for database and file access) than earlier versions of .NET. You want to use APIs which conform to the Task-based Asynchronous Pattern (TAP). Then, using async/await you can write your server-side code so that it reads a bit like synchronous code, but actually executes asynchronous. So for example, you might have:
Guid userId = await FetchUserIdAsync();
IEnumerable<Message> messages = await FetchMessagesAsync(userId);
Even though you need to "wait" while each of these operations talks place, you do so without blocking a thread. The C# compiler takes care of building a state machine for you. There's no need to explicitly write callbacks which frequently turn into spaghetti code - the compiler does it all.
You need to make sure that whatever web/web-service framework you use supports asynchrony, and it should just manage the rest, using as few threads as it can get away with.
Follow the two links above to find out more about the asynchrony support in C# 5 - it's a huge topic, and I'm sure you'll have more questions afterwards, but when you've read a bit more you should be able to ask very specific questions instead of the current broad one.