Async method waiting for end? - c#

I am rewriting some of my component management to use async start methods. Sadly it looks like a call to an async method WITHOUT await, still does await the result?
Can anyone enlighten me?
I am calling:
public async Task StartAsync() {
await DoStartProcessingAsync();
}
which in itself is calling a slow implementation of protected abstract Task DoStartProcessingAsync(); - slow because it dome some EF calls, then creates an appdomain etc. - takes "ages".
The actual call is done in the form:
x.StartAsync().Forget();
with "Forget" being a dummy function just to avoid the "no await" warning:
public static void Forget(this Task task) {
}
Sadly, this sequence - is waiting for the slow DoStartAsync method to complete, and I see no reason for that. I am quite old in C#, but quite new to async/await and I was under the impression that, unless I await for the async task - the method would complete. As such, I expected the call to StartAsyc().Forget() to return immediatly. INSTEAD stack trace shows the thread going all the way into the DoStartProcessingAsync() method without any async processing happening.
Anyone can enlighten me on my mistake?

What your trying to achieve here is a fire and forget type mechanism. So async/await isn't really what you want. Your not wanting to await anything.
These are designed to free up threads for long running processes. Right now your returning a Task using an await and then "forgetting" it. So why return the Task at all?
Your freeing up the thread for the long running process, but your also queuing a process that ultimately does nothing (this is adding overhead that you could likely do without).
Simply doing this, would probably make more sense:
public void StartAsync() {
Task.Run(() => DoStartProcessingAsync());
}
One thing to bear in mind is that your now using a ThreadPool thread not a UI thread (depending on what is actually calling this).

Related

C# Convert async code to run sync in certain method(Constructor/Main/PropertyGetter/PropertySetter) without possibility of deadlock

I have a bunch of async code, I have tried to expand my asyc code as large as possible in my codebase. I am here looking for an safe approach to convert async code to async (wait it finish then return result). I have tied looking on the internet but they either way to complex or may cause deadlocks.
Here is my code:
protected virtual DbData GetDbData()
{
return StorageProvider.RefreshAsync().Result;
}
The GetDbData will be used as a property getter something like:
public override DbData Data
{
get => GetDbData();
set => SetDbData(value);
}
and in constructor
public CachedDataManager(IStorageProvider storageProvider) : base(storageProvider)
{
_cachedData = StorageProvider.RefreshAsync().Result;
}
or for the async method without return value
public CachedDataManager(IStorageProvider storageProvider) : base(storageProvider)
{
DoSomeWorkAsync().GetAwaiter().GetResult();
}
private Task DoSomeWorkAsync()
{
//Assume heavy load.
Task.Delay(5000);
return Task.CompletedTask;
}
Result may causing a deadlock because of the SynchronizationContext when calling in the UI thead (what I know)
All the other solution told me to expand async code as far as possible, I tried, but I can't do it with constructor/property getter
Are there exist some solution similar to Task.Result/Task.Wait/Task.RunSynchronously that does not causes any problems(eg deadlock)?
Also I am not sure about DoSomeWorkAsync().GetAwaiter().GetResult(); it does causes problems with SynchronizationContext or not. I am a noob on this. Please help
A task (what async methods return) can contain every type of logic. Suppose you are calling an async Task method from the Thread A, and you want to synchronously wait for the task to complete. Now let's think carefully what could be the conditions for a deadlock: basically we have to guarantee that the Task do not schedule anything "asynchronously" on the Thread A! If that's the case you can safely call task.GetAwaiter().GetResult(). If not you can't. It's a conceptual limit. There is not a general way to avoid deadlocks.
For example suppose that the Thread A is the UI thread. If the async Task contains a "real" await operation (that is, an await over a Task that is not completed yet, such as Task.Delay(100)), we are already in a bad spot: why? Because the code after the await is wrapped into an Action and scheduled through the Synchronization Context in the UI Thread. So the task is waiting for some code to execute in the UI thread, but the UI thread is waiting for the task to complete
Another example: suppouse the Task method we are awaiting is not async (so contains synchronous code, like Task.Run(VoidMethod)) and that at some point there is a call to Dispatcher.Invoke(). We still have a deadlock: the task to complete should wait for some code to be executed on the UI Thread. But the UI Thread is waiting for that task to complete..
Side note. While in the first example we can do some tricks such as change the Synchronization context temporarily in order to avoid the continuations to run on the UI Thread, in the second example there are no chance to make it work, it's conceptually wrong if you thing about it. So there isn't a general way.
It really depends.

Async not working as I expected

I've read all I can find on async programming in asp.net (c#). I've made sense of most of how it's supposed to work and when it should be used. Yet I find basic examples not working as I expect. Without Task.Run it doesn't seem to actually run asynchronously.
Can someone tell me what I'm missing in this example?
Say the code is like so
public async Task SubTask2()
{
LongRunningOperation2();
Response.Write("<br>------------------------ Finished -------------------------<br>");
}
private async Task<Boolean> LongRunningOperation1()
{
int counter;
for (counter = 0; counter < 50000; counter++)
{
Response.Write(counter + "<br>");
}
return await Task.FromResult<bool>(true);
}
private async Task<Boolean> LongRunningOperation2()
{
await LongRunningOperation1();
Response.Write("<br>------------------------ Long Task -------------------------<br>");
return true;
}
Shouldn't LongRunningOperation2() return to SubTask2() and print "finished" before or while writing out numbers? Instead it prints finished at the end. Using Task.Run works as expected but then I don't see the point of ever not using Task.Run
A design consideration of the async/await pattern is that sometimes code that has an async signature might return synchronously (immediately) - perhaps due to caching or local data buffering (reading data from a socket, perhaps, and having spare data left to consume from the buffer), or perhaps due to IoC etc providing a synchronous implementation of an asynchronous signature. In that scenario, the entire engine is designed to optimize by not doing anything as callbacks, but continuing to run synchronously. This is not an edge-case - recent C# updates have extended this by adding support for custom awaitables (in particular: ValueTask<T>) to make this even more efficient in the case when something completes with a synchronous but non-trivial result.
The purpose of async is to facilitate scenarios that have genuinely async components, freeing up the thread to do more useful things than waiting for an async operation to complete. It is not about parallelization.
In your case, all of your code is actually synchronous, so it continues to run synchronously all the way through.
First, you're missing await in SubTask2(), so it actually runs synchronously (waits for LongRunningOperation2() to finish).
Secondly, even with asynchronous execution, "finished" wouldn't be printed before LongRunningOperation2() finished it's work. The point of using it is to free the thread, so it can do some other work in the meantime (e.g. handle another request).

how and when to fetch return from awaitable(async) method

I am pretty sure, this was answered already and I read many related stuff but somehow I am not getting it to work in my code. Here is the exact code base.
I have this async method in my library, that returns a string upon doing some DB entries:
public class MyLibrary
{
public async Task<string> DoSomethingAsync()
{
return await DoAsync();
}
// some private method, with multiple parameters
private Task<string> DoAsync()
{
return Task.Run(() => Do());
}
}
Now on UI, below resulted a frozen state or deadlock:
var myTask = MyLibraryobject.DoSomethingAsync();
console.Write(myTask.Result);
Since my call is awaitable, I think, UI thread waits for my call to finish its business and populate the result, doesn't it? Or since the call is running on another thread, the task might not yet completed when my cursor hits the line 2. So what now? the cursor will wait till the task gets completed or the line 2 gets executed whenever the task gets completed? sounds synchronous to me..
Also if at all, I want to 'exlicitly' wait till the task gets finished, how do i enforce that? some posts, suggested in doing like below, which gave me the result, but created some more confusion:
var myTask = Task.Run(async () => await MyLibraryobject.DoSomethingAsync());
myTask.Wait();
console.Write(myTask.Result);
What is happening above? why should i create another task and set it to wait? can't I wait for the thread, used by the async method? Again, i am clearly missing some basic stuff here.
Lastly, this is an async call, but the UI thread is waiting for it to be completed thus gives me an impression that it's synchronous. Am I thinking it right? Then what is the main purpose of async methods, which return something, and UI waits for it to complete?
Also what's the difference between a fire-and-forget call being non-async and async? is there any benefit of returning Task, instead of void, for such calls?
I am pretty sure, some broken link that connects all these pieces together in my brain. Can someone explain that to me, please??
You should probably start with my async intro and follow up with my article on async best practices. They answer almost all your questions.
For the details...
how and when to fetch return from awaitable(async) method
You should use await to get the result from an async task.
I have this async method in my library, that returns a string upon doing some DB entries
Then it should not be using Task.Run. It should be using naturally-asynchronous APIs, e.g., Entity Framework's FirstAsync.
Since my call is awaitable, I think, UI thread waits for my call to finish its business and populate the result, doesn't it?
No. The UI is blocking because your code is calling Result. Result is a blocking call.
sounds synchronous to me..
That's because you're making it synchronous by using Result. If you use await, the code will execute serially, but asynchronously.
Also if at all, I want to 'exlicitly' wait till the task gets finished, how do i enforce that?
Your code is already doing that. It's explicitly blocking until the task is complete. If you change it to properly use await, it will be explicitly waiting (but not blocking) until the task is complete.
some posts, suggested in doing like below
No. Don't use Task.Run unnecessarily.
can't I wait for the thread, used by the async method?
Pure async methods don't have threads that they use.
Then what is the main purpose of async methods, which return something, and UI waits for it to complete?
Async makes sense when it's consumed with await.
Now on UI, below resulted a frozen state or deadlock:
var myTask = MyLibraryobject.DoSomethingAsync();
This is blocking the UI because it is not awaited. You simply need to await an async method
string res = await MyLibraryobject.DoSomethingAsync();
and the above should be placed in the UI inside an async context too.
Edit - reply to comment do "you mean another wrapper async method, which returns Task<string>..."? No,I don't. When I wrote "inside an async context" I meant to add the async keyword to a subscribed event, like a button click, if you are in the code behind or to your delegate command implementation, if you are in a more advanced MVVM implementation of the GUI.
Furthermore, your class library is supposed to do something truly asynchronous, not just starting a task and wrapping it inside a formally async method, like it is your DoAsync.
Edit - in reply to comment "how should avoid" it? If you can't do async all the way, just keep the library and the API sync and unblock the UI by starting a separate thread to call the sync api.

fire and forget an async Task method sometimes not invoke

I have an async method:
public async Task DoSomethingAsync(){
...
await ...
await ...
....
return await SaveAsync();
}
In most time, I call this method by:
await DoSomethingAsync()
This call works as expected. But somewhere, I need to call this method as fire and forget:
public void OtherMethod()
{
...
DoSomethingAsync(); //fire and forget here
}
In this case, sometimes the Task DoSomethingAsync() runs and completes, but sometimes the task never invoked (or invoke some awaits within DoSomethingAsync() but never complete the last await SaveAsync();).
I'm trying to make sure the task will be invoked in fire and forget manner by these code:
public void OtherMethod()
{
...
Task.Factory.StartNew(() =>
{
await DoSomethingAsync();
}); //fire and forget again here
}
However, this does not work as expectation. So my questions are:
How to make the call to DoSomethingAsync() without await will always run and complete? (I don't care the case AppDomain restart/crash)
If I remove all async/await code within DoSomethingAsync() and replace await by .ContinueWith(), then the call to Task DoSomethingAsync() (not have async in method declaration) will be invoked and sure to complete (ignore case AppDomain restart/crash), if yes, how long from the call (I don't think that I'll be happy if the Task will be invoked after 10 minutes)?
You're probably getting an exception somewhere in DoSomethingAsync, which you cannot observe because you're ignoring the task. This is exactly the behavior you're asking for, since you're telling the code to "forget" the task.
To observe the exception, you cannot "forget" the task:
public Task OtherMethodAsync()
{
...
return DoSomethingAsync();
}
And at some point, await (or Wait) the returned task. That is how you know the task will run and complete.
The awaits should be working fine, so there is likely something else going on here that is holding up one or more of your methods being awaited. There are a few possibilities:
You have a deadlock somewhere in one of your methods, preventing it from completing and blocking the await from resuming.
All of your thread pool threads are blocking for some reason, preventing pending Tasks from running.
You're running the async method in a synchronization context and something is holding up the context, preventing it from running the dispatched callbacks. Typically the context would be the UI thread and generally this is pretty obvious, since it locks up your application UI.
If you can attach with the VS debugger and observe what's happening, try pausing and looking at the Parallel Stacks view. This should help narrow down which possibilities to consider.
As Stephen pointed out, it's also possible that an Exception is occurring when you're calling it fire-and-forget. If you're not already, make sure you handle TaskScheduler.UnobservedTaskException to log any events like this. Note that this is called from the finalizer, so the time at which it gets called is non-deterministic. This can make debugging tricky, since the event might not fire until much later than the actual event that caused the exception. As such, I recommend following Stephen's advice and saving the Task to await or Wait somewhere else later.
ASP.NET generally does not allow fire-and-forget (async void) operations to be kicked off from within a request. See https://stackoverflow.com/a/22484832/59641 for a further explanation of this behavior and some potential workarounds.

Run an async function in another thread

I'm evaluating the Async CTP.
How can I begin execution of an async function on another thread pool's thread?
static async Task Test()
{
// Do something, await something
}
static void Main( string[] args )
{
// Is there more elegant way to write the line below?
var t = TaskEx.Run( () => Test().Wait() );
// Doing much more in this same thread
t.Wait(); // Waiting for much more then just this single task, this is just an example
}
I'm new (my virginal post) to Stack Overflow, but I'm jazzed that you're asking about the Async CTP since I'm on the team working on it at Microsoft :)
I think I understand what you're aiming for, and there's a couple of things you're doing correctly, to get you there.
What I think you want:
static async Task Test()
{
// Do something, await something
}
static void Main(string[] args)
{
// In the CTP, use Task.RunEx(...) to run an Async Method or Async Lambda
// on the .NET thread pool
var t = TaskEx.RunEx(Test);
// the above was just shorthand for
var t = TaskEx.RunEx(new Func<Task>(Test));
// because the C# auto-wraps methods into delegates for you.
// Doing much more in this same thread
t.Wait(); // Waiting for much more then just this single task, this is just an example
}
Task.Run vs. Task.RunEx
Because this CTP installs on top of .NET 4.0, we didn't want to patch the actual System.Threading.Tasks.Task type in mscorlib. Instead, the playground APIs are named FooEx when they conflicted.
Why did we name some of them Run(...) and some of the RunEx(...)? The reason is because of redesigns in method overloading that we hadn't completed yet by the time we released the CTP. In our current working codebase, we've actually had to tweak the C# method overloading rules slightly so that the right thing happens for Async Lambdas - which can return void, Task, or Task<T>.
The issue is that when async method or lambdas return Task or Task<T>, they actually don't have the outer task type in the return expression, because the task is generated for you automatically as part of the method or lambda's invocation. This strongly seems to us like the right experience for code clarity, though that does make things quite different before, since typically the expression of return statements is directly convertible to the return type of the method or lambda.
So thus, both async void lambdas and async Task lambdas support return; without arguments. Hence the need for a clarification in method overload resolution to decide which one to pick. Thus the only reason why you have both Run(...) and RunEx(...) was so that we would make sure to have higher quality support for the other parts of the Async CTP, by the time PDC 2010 hit.
How to think about async methods/lambdas
I'm not sure if this is a point of confusion, but I thought I'd mention it - when you are writing an async method or async lambda, it can take on certain characteristics of whoever is invoking it. This is predicated on two things:
The type on which you are awaiting
And possibly the synchronization context (depending on above)
The CTP design for await and our current internal design are both very pattern-based so that API providers can help flesh out a vibrant set of things that you can 'await' on. This can vary based on the type on which you're awaiting, and the common type for that is Task.
Task's await implementation is very reasonable, and defers to the current thread's SynchronizationContext to decide how to defer work. In the case that you're already in a WinForms or WPF message loop, then your deferred execution will come back on the same message loop (as if you used BeginInvoke() the "rest of your method"). If you await a Task and you're already on the .NET threadpool, then the "rest of your method" will resume on one of the threadpool threads (but not necessarily the same one exactly), since they were pooled to begin with and most likely you're happy to go with the first available pool thread.
Caution about using Wait() methods
In your sample you used:
var t = TaskEx.Run( () => Test().Wait() );
What that does is:
In the surrounding thread synchronously call TaskEx.Run(...) to execute a lambda on the thread pool.
A thread pool thread is designated for the lambda, and it invokes your async method.
The async method Test() is invoked from the lambda. Because the lambda was executing on the thread pool, any continuations inside Test() can run on any thread in the thread pool.
The lambda doesn't actually vacate that thread's stack because it had no awaits in it. The TPL's behavior in this case depends on if Test() actually finished before the Wait() call. However, in this case, there's a real possibility that you will be blocking a thread pool thread while it waits for Test() to finish executing on a different thread.
That's the primary benefit of the 'await' operator is that it allows you to add code that executes later - but without blocking the original thread. In the thread pool case, you can achieve better thread utilization.
Let me know if you have other questions about the Async CTP for VB or C#, I'd love to hear them :)
It's usually up to the method returning the Task to determine where it runs, if it's starting genuinely new work instead of just piggy-backing on something else.
In this case it doesn't look like you really want the Test() method to be async - at least, you're not using the fact that it's asynchronous. You're just starting stuff in a different thread... the Test() method could be entirely synchronous, and you could just use:
Task task = TaskEx.Run(Test);
// Do stuff
t.Wait();
That doesn't require any of the async CTP goodness.
There would be, if this wasn't a console application. For example, if you do this in a Windows Forms application, you could do:
// Added to a button click event, for example
public async void button1_Click(object sender, EventArgs e)
{
// Do some stuff
await Test();
// Do some more stuff
}
However, there is no default SynchronizationContext in a console, so that won't work the way you'd expect. In a console application, you need to explicitly grab the task and then wait at the end.
If you're doing this in a UI thread in Windows Forms, WPF, or even a WCF service, there will be a valid SynchronizationContext that will be used to marshal back the results properly. In a console application, however, when control is "returned" at the await call, the program continues, and just exits immediately. This tends to mess up everything, and produce unexpected behavior.

Categories

Resources