async await and shared objects - c#

I'm using the async / await pattern to perform some CPU heavy operations on an object (my method is awaitable), which works as supposed without blocking the UI thread.
However, when i pass the object as a parameter to the ctor of a new window (the new window is a logging window that needs access to the processed object), my UI thread blocks (which I kinda understand why).
to get around this I could wrap the execution of the calculation in a
Task.Run(async () => { await _myObject.PerformCalculations(); });
and then simply call
var logWindow = new LogWindow(_myObject);
logWindow.Show();
This works (of course) but i have a lot of dispatcher calls when the object raises events, which I wouldn't have to deal with if I could do without the Task.Run call.
So, my question is, can I somehow do without the Task.Run call and still pass the object to the logging window without blocking my UI thread?
EDIT
I'm sorry for the stripped down example, I actually intended to make the question as simple as possible to understand and failed miserably.
In a more general way: I have an object that raises events on certain conditions. When an event is raised, I want to perform updates on the UI. An event always fires from the thread that was created using Task.Run(...). Hence, dispatcher calls to the UI thread. So, I want to perform the calculations using async / await (already works) and pass the object to my logging window (blocks).
When I use Task.Run, everything works of course, but wherever I subscribe to an event of the object from the UI thread I have to use dispatcher calls to the UI thread, because the event fires from the thread that Task.Run created. These dispatcher calls I would like to avoid. In fact, if I wouldn't pass the object to the logging window, and call the Show() method, the UI thread wouldn't block and everything would work as supposed. No dispatcher calls needed in the event handlers.

It's kind of hard to get a clear picture of your situation. But it looks to me like you could do with some refactoring.
Consider PerformCalculations: this is a method returning Task (thus advertising itself as async-friendly) that does heavy CPU usage (thus not actually being async-friendly). The first thing I would look at is dividing up the logic in PerformCalculations so that the CPU-bound portions use their own Task.Run, leaving PerformCalcuations as an async method that doesn't (directly) hit the CPU:
public async Task PerformCalculationsAsync()
{
while (...)
{
await Task.Run(<next calculations>);
RaiseEvent();
}
}
The point of this refactoring is to divide the CPU code in Task.Run from the UI-ish code raising events. Also consider using the standard IProgress<T> approach if your events are logically progress updates or if this kind of refactoring would be too difficult for your code; IProgress<T>.Report can be called from any thread.
You may also find my posts on async constructors and async properties (particularly the data-binding section) to be helpful.

// awaitable as well - await this in another async void/Task method (e.g. commanding)
public async Task MyAsyncProcess()
{
await _myObject.PerformCalculations();
var logWindow = new LogWindow(_myObject);
}
Task.Run() executes an asynchronous method synchronously, so in this case you pretty much lack of use of the async/await pattern. Make the method where you execute your code async as well and await it somewhere else. Or alternatively use some FireAndForget logic.

Related

which is the difference between task.whenAll and configurewait?

I have an async method that get data from a database:
private async Task getDataAsync()
{
await getDataFromDatabaseAsync();
}
I have a contructor that uses this method, in this way:
public MyViewModel()
{
Task.WhenAll(getDataAsync());
//getDataAsync().ConfigureAwait(false);
//next line of code
}
The only way that I get to avoid the applications isn't blocked is using one the two options, both seems to work fine. I can use WhenAll or I can use ConfigureAwait(false).
Another options it is calling the method getDataASync() inside a task, but I guess it is a worse option becase it takes more resources.
So I would like to know which is the differences between WhenAll and ConfigureAwait.
When I use WhenAll in this way, the line of code "next line of code" is run after the async method is finisihed or it will run before finish?
Thanks.
There is a common misconception that when you make a method async, it will be actually executed asynchronously (i.e. on a separate thread). That is not the case: async and await are a means to synchronize already asnychronous code. If you have nothing that is executed on a separate thread, your async code will run fully synchronously to the end.
Since getDataAsync is executed on the same thread as the MyViewModel constructor, you can run into a deadlock, since the thread waits for itself. When you use ConfigureAwait, you can avoid this situation.
Whether you actually should do that is a different question. What you are actually doing with ConfigureAwait is to start the task and to allow the await to continue on a separate context (which can be on a separate thread). Apart from the fact that you are not even using await here, continuation in a different context can become a problem when you want to execute UI operations after the await.
If you want to be sure that you can wait for getDataAsync in your constructor, you can use Task.Run to force execution in the thread pool:
var getDataTask = Task.Run((Func<Task>)getDataAsync);
//Do something else
getDataTask.Wait();
Everything you execute between Task.Run and the Wait() can run during the execution of getDataAsync. Whether parallelism is actually worth it here depends on what else you do until the Wait().
What you are doing in the MyViewModel constructor is to finally synchronize all asynchronous operations and make the execution of the constructor synchronous. If you want to run that operation asynchronously, you would need to start another task to do it. So you should be really sure that beyond that point async is not required anymore. If it is, run the initialization on another async method, await getDataAsync() there and synchronize somewhere up the call chain.

Difference between Task.WhenAll(Task.Run(async method)) and Task.WhenAll(async method)

I've been trying to figure out why the UI was blocking from a ViewModel method, and realized that this part of the code:
await Task.WhenAll(getOutput1(), getOutput2());
was the problem. I managed to unblock the UI by using:
await Task.WhenAll(Task.Run(() => getOutput1()), Task.Run(() => getOutput2()));
getOutput1() and getOutput2() are both async with Task return types in the ViewModel, and the code is called from the View.
What's the difference with calling Task.WhenAll when I call Task.Run() and just directly supplying the task?
What's the difference with calling Task.WhenAll when I call Task.Run() and just directly supplying the task?
Calling the methods directly will invoke them on the UI thread. Calling them from within Task.Run will invoke them on a thread pool thread.
Conclusion: getOutput1 and/or getOutput2 are not actually asynchronous. (It is entirely possible for a method to return Task - and thus appear asynchronous - but in reality just block synchronously).
If the methods are pure async operations then you should not use Task.Run while calling them from the UI thread and it will work properly.
However if the methods are also involved in a long running CPU bound work, the UI thread won't be blocked while the async I/O operation is executing but will be while the CPU bound work is.
In this scenario you need the use Task.Run while you are calling the methods even though the methods already look like a async ones, because the methods are actually a combination of synchronous and asynchronous operations and you don't want to block the UI while the synchronous work is done.
Another option instead of using Task.Run from the ViewModel is to use ConfigureAwait(false) while awaiting the I/O async operations in your methods, doing that will inform to the rest of the method after the await part that it does not need the original context it had (which is probably the UI one) and that the rest of the method can also be executed in another ThreadPool thread instead.
Please refer this question for more info about async and await methods that combine I/O and CPU bound works.

Using ThreadPool and Task.Wait inside an Async/Await Method

I just encountered this code. I immediately started cringing and talking to myself (not nice things). The thing is I don't really understand why and can't reasonably articulate it. It just looks really bad to me - maybe I'm wrong.
public async Task<IHttpActionResult> ProcessAsync()
{
var userName = Username.LogonName(User.Identity.Name);
var user = await _user.GetUserAsync(userName);
ThreadPool.QueueUserWorkItem((arg) =>
{
Task.Run(() => _billing.ProcessAsync(user)).Wait();
});
return Ok();
}
This code looks to me like it's needlessly creating threads with ThreadPool.QueueUserWorkItem and Task.Run. Plus, it looks like it has the potential to deadlock or create serious resource issues when under heavy load. Am I correct?
The _billing.ProcessAsync() method is awaitable(async), so I would expect that a simple "await" keyword would be the right thing to do and not all this other baggage.
I believe Scott is correct with his guess that ThreadPool.QueueUserWorkItem should have been HostingEnvironment.QueueBackgroundWorkItem. The call to Task.Run and Wait, however, are entirely nonsensical - they're pushing work to the thread pool and blocking a thread pool thread on it, when the code is already on the thread pool.
The _billing.ProcessAsync() method is awaitable(async), so I would expect that a simple "await" keyword would be the right thing to do and not all this other baggage.
I strongly agree.
However, this will change the behavior of the action. It will now wait until Billing.ProcessAsync is completed, whereas before it would return early. Note that returning early on ASP.NET is almost always a mistake - I would say any "billing" processing would be even more certainly a mistake. So, replacing this mess with await will make the app more correct, but it will cause the ProcessAsync action to take longer to return to the client.
It's strange, but depending on what the author is trying to achieve, it seems ok to me to queue a work item in the thread pool from inside an async method.
This is not as starting a thread, it's just queueing an action to be done in a ThreadPool's thread when there is a free one. So the async method (ProcessAsync) can continue and don't need to care about the result.
The weird thing is the code inside the lambda to be enqueued in the ThreadPool. Not only the Task.Run() (which is superflous and just causes unnecessary overhead), but to call an async method without waiting for it to finish is bad inside a method that should be run by the ThreadPool, because it returns the control flow to the caller when awaiting something.
So the ThreadPool eventually thinks this method is finished (and the thread free for the next action in the queue), while actually the method wants to be resumed later.
This may lead to very undefined behaviour. This code may have been working (in certain circumstances), but I would not rely on it and use it as productive code.
(The same goes for calling a not-awaited async method inside Task.Run(), as the Task "thinks" it's finished while the method actually wants to be resumed later).
As solution I'd propose to simply await that async method, too:
await _billing.ProcessAsync(user);
But of course without any knowledge about the context of the code snippet I can't guarantee anything. Note that this would change the behaviour: while until now the code did not wait for _billing.ProcessAsync() to finsih, it would now do. So maybe leaving out await and just fire and forget
_billing.ProcessAsync(user);
maybe good enough, too.

Is there a way to signal a System.Threading.Tasks.Task complete?

I have a library that is a complicated arbiter of many network connections. Each method of it's primary object takes a delegate, which is called when the network responds to a given request.
I want to translate my library to use the new .NET 4.5 "async/await" pattern; this would require me to return a "Task" object, which would signal to the user that the asynchronous part of the call is complete. Creating this object requires a function for the task to represent - As far as my understanding, it is essentially a lightweight thread.
This doesn't really fit the design of my library - I would like the task to behave more like an event, and directly signal to the user that their request has completed, rather then representing a function. Is this possible? Should i avoid abusing the "async/await" pattern in this way?
I don't know if I'm wording this very well, I hope you understand my meaning. Thank you for any help.
As far as my understanding, it is essentially a lightweight thread.
No, that's not really true. I can be true, under certain circumstances, but that's just one usage of Task. You can start a thread by passing it a delegate, and having it execute it (usually asynchronously, possibly synchronously, and by default using the thread pool).
Another way of using threads is through the use of a TaskCompletionSource. When you do that the task is (potentially) not creating any threads, using the thread pool, or anything along those lines. One common usage of this model is converting an event-based API to a Task-based API:
Let's assume, just because it's a common example, that we want to have a Task that will be completed when a From that we have is closed. There is already a FormClosed event that fires when that event occurs:
public static Task WhenClosed(this Form form)
{
var tcs = new TaskCompletionSource<object>();
form.FormClosing += (_, args) =>
{
tcs.SetResult(null);
};
return tcs.Task;
}
We create a TaskCompletionSource, add a handler to the event in question, in that handler we signal the completion of the task, and the TaskCompletionSource provides us with a Task to return to the caller. This Task will not have resulted in any new threads being created, it won't use the thread pool, or anything like that.
You can have a Task/Event based model using this construct that appears quite asynchronous, but only using a single thread to do all work (the UI thread).
In general, anytime you want to have a Task that represents something other than the execution of a function you'll want to consider using a TaskCompletionSource. It's usually the appropriate conceptual way to approach the problem, other than possibly using one of the existing TPL methods, such as WhenAll, WhenAny, etc.
Should I avoid abusing the "async/await" pattern in this way?
No, because it's not abuse. It's a perfectly appropriate use of Task constructs, as well as async/await. Consider, for example, the code that you can write using the helper method that I have above:
private async void button1_Click(object sender, EventArgs e)
{
Form2 popup = new Form2();
this.Hide();
popup.Show();
await popup.WhenClosed();
this.Show();
}
This code now works just like it reads; create a new form, hide myself, show the popup, wait until the popup is closed, and then show myself again. However, since it's not a blocking wait the UI thread isn't blocked. We also don't need to bother with events; adding handlers, dealing with multiple contexts; moving our logic around, or any of it. (All of that happens, it's just hidden from us.)
I want to translate my library to use the new .NET 4.5 "async/await" pattern; this would require me to return a "Task" object, which would signal to the user that the asynchronous part of the call is complete.
Well, not really - you can return anything which implements the awaitable pattern - but a Task is the simplest way of doing this.
This doesn't really fit the design of my library - I would like the task to behave more like an event, and directly signal to the user that their request has completed, rather then representing a function.
You can call Task.ContinueWith to act as a "handler" to execute when the task completes. Indeed, that's what TaskAwaiter does under the hood.
Your question isn't terribly clear to be honest, but if you really want to create a Task which you can then force to completion whenever you like, I suspect you just want TaskCompletionSource<TResult> - you call the SetResult, SetCanceled or SetException methods to indicate the appropriate kind of completion. (Or you can call the TrySet... versions.) Use the Task property to return a task to whatever needs it.

Async/Await - is it *concurrent*?

I've been considering the new async stuff in C# 5, and one particular question came up.
I understand that the await keyword is a neat compiler trick/syntactic sugar to implement continuation passing, where the remainder of the method is broken up into Task objects and queued-up to be run in order, but where control is returned to the calling method.
My problem is that I've heard that currently this is all on a single thread. Does this mean that this async stuff is really just a way of turning continuation code into Task objects and then calling Application.DoEvents() after each task completes before starting the next one?
Or am I missing something? (This part of the question is rhetorical - I'm fully aware I'm missing something :) )
It is concurrent, in the sense that many outstanding asychronous operations may be in progress at any time. It may or may not be multithreaded.
By default, await will schedule the continuation back to the "current execution context". The "current execution context" is defined as SynchronizationContext.Current if it is non-null, or TaskScheduler.Current if there's no SynchronizationContext.
You can override this default behavior by calling ConfigureAwait and passing false for the continueOnCapturedContext parameter. In that case, the continuation will not be scheduled back to that execution context. This usually means it will be run on a threadpool thread.
Unless you're writing library code, the default behavior is exactly what's desired. WinForms, WPF, and Silverlight (i.e., all the UI frameworks) supply a SynchronizationContext, so the continuation executes on the UI thread (and can safely access UI objects). ASP.NET also supplies a SynchronizationContext that ensures the continuation executes in the correct request context.
Other threads (including threadpool threads, Thread, and BackgroundWorker) do not supply a SynchronizationContext. So Console apps and Win32 services by default do not have a SynchronizationContext at all. In this situation, continuations execute on threadpool threads. This is why Console app demos using await/async include a call to Console.ReadLine/ReadKey or do a blocking Wait on a Task.
If you find yourself needing a SynchronizationContext, you can use AsyncContext from my Nito.AsyncEx library; it basically just provides an async-compatible "main loop" with a SynchronizationContext. I find it useful for Console apps and unit tests (VS2012 now has built-in support for async Task unit tests).
For more information about SynchronizationContext, see my Feb MSDN article.
At no time is DoEvents or an equivalent called; rather, control flow returns all the way out, and the continuation (the rest of the function) is scheduled to be run later. This is a much cleaner solution because it doesn't cause reentrancy issues like you would have if DoEvents was used.
The whole idea behind async/await is that it performs continuation passing nicely, and doesn't allocate a new thread for the operation. The continuation may occur on a new thread, it may continue on the same thread.
The real "meat" (the asynchronous) part of async/await is normally done separately and the communication to the caller is done through TaskCompletionSource. As written here http://blogs.msdn.com/b/pfxteam/archive/2009/06/02/9685804.aspx
The TaskCompletionSource type serves two related purposes, both alluded to by its name: it is a source for creating a task, and the source for that task’s completion. In essence, a TaskCompletionSource acts as the producer for a Task and its completion.
and the example is quite clear:
public static Task<T> RunAsync<T>(Func<T> function)
{
if (function == null) throw new ArgumentNullException(“function”);
var tcs = new TaskCompletionSource<T>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
T result = function();
tcs.SetResult(result);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
Through the TaskCompletionSource you have access to a Task object that you can await, but it isn't through the async/await keywords that you created the multithreading.
Note that when many "slow" functions will be converted to the async/await syntax, you won't need to use TaskCompletionSource very much. They'll use it internally (but in the end somewhere there must be a TaskCompletionSource to have an asynchronous result)
The way I like to explain it is that the "await" keyword simply waits for a task to finish but yields execution to the calling thread while it waits. It then returns the result of the Task and continues from the statement after the "await" keyword once the Task is complete.
Some people I have noticed seem to think that the Task is run in the same thread as the calling thread, this is incorrect and can be proved by trying to alter a Windows.Forms GUI element within the method that await calls. However, the continuation is run in the calling thread where ever possible.
Its just a neat way of not having to have callback delegates or event handlers for when the Task completes.
I feel like this question needs a simpler answer for people. So I'm going to oversimplify.
The fact is, if you save the Tasks and don't await them, then async/await is "concurrent".
var a = await LongTask1(x);
var b = await LongTask2(y);
var c = ShortTask(a, b);
is not concurrent. LongTask1 will complete before LongTask2 starts.
var a = LongTask1(x);
var b = LongTask2(y);
var c = ShortTask(await a, await b);
is concurrent.
While I also urge people to get a deeper understanding and read up on this, you can use async/await for concurrency, and it's pretty simple.

Categories

Resources