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.
Related
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.
I don't quite understand the difference between Task.Wait and await.
I have something similar to the following functions in a ASP.NET WebAPI service:
public class TestController : ApiController
{
public static async Task<string> Foo()
{
await Task.Delay(1).ConfigureAwait(false);
return "";
}
public async static Task<string> Bar()
{
return await Foo();
}
public async static Task<string> Ros()
{
return await Bar();
}
// GET api/test
public IEnumerable<string> Get()
{
Task.WaitAll(Enumerable.Range(0, 10).Select(x => Ros()).ToArray());
return new string[] { "value1", "value2" }; // This will never execute
}
}
Where Get will deadlock.
What could cause this? Why doesn't this cause a problem when I use a blocking wait rather than await Task.Delay?
Wait and await - while similar conceptually - are actually completely different.
Wait will synchronously block until the task completes. So the current thread is literally blocked waiting for the task to complete. As a general rule, you should use "async all the way down"; that is, don't block on async code. On my blog, I go into the details of how blocking in asynchronous code causes deadlock.
await will asynchronously wait until the task completes. This means the current method is "paused" (its state is captured) and the method returns an incomplete task to its caller. Later, when the await expression completes, the remainder of the method is scheduled as a continuation.
You also mentioned a "cooperative block", by which I assume you mean a task that you're Waiting on may execute on the waiting thread. There are situations where this can happen, but it's an optimization. There are many situations where it can't happen, like if the task is for another scheduler, or if it's already started or if it's a non-code task (such as in your code example: Wait cannot execute the Delay task inline because there's no code for it).
You may find my async / await intro helpful.
Based on what I read from different sources:
An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.
To wait for a single task to complete, you can call its Task.Wait method. A call to the Wait method blocks the calling thread until the single class instance has completed execution. The parameterless Wait() method is used to wait unconditionally until a task completes. The task simulates work by calling the Thread.Sleep method to sleep for two seconds.
This article is also a good read.
Some important facts were not given in other answers:
async/await is more complex at CIL level and thus costs memory and CPU time.
Any task can be canceled if the waiting time is unacceptable.
In the case of async/await we do not have a handler for such a task to cancel it or monitoring it.
Using Task is more flexible than async/await.
Any sync functionality can by wrapped by async.
public async Task<ActionResult> DoAsync(long id)
{
return await Task.Run(() => { return DoSync(id); } );
}
async/await generate many problems. We do not know if await statement will be reached without runtime and context debugging. If first await is not reached, everything is blocked. Sometimes even when await seems to be reached, still everything is blocked:
https://github.com/dotnet/runtime/issues/36063
I do not see why I must live with the code duplication for sync and async method or using hacks.
Conclusion: Creating Tasks manually and controlling them is much better. Handler to Task gives more control. We can monitor Tasks and manage them:
https://github.com/lsmolinski/MonitoredQueueBackgroundWorkItem
Sorry for my english.
I don't quite understand the difference between Task.Wait and await.
I have something similar to the following functions in a ASP.NET WebAPI service:
public class TestController : ApiController
{
public static async Task<string> Foo()
{
await Task.Delay(1).ConfigureAwait(false);
return "";
}
public async static Task<string> Bar()
{
return await Foo();
}
public async static Task<string> Ros()
{
return await Bar();
}
// GET api/test
public IEnumerable<string> Get()
{
Task.WaitAll(Enumerable.Range(0, 10).Select(x => Ros()).ToArray());
return new string[] { "value1", "value2" }; // This will never execute
}
}
Where Get will deadlock.
What could cause this? Why doesn't this cause a problem when I use a blocking wait rather than await Task.Delay?
Wait and await - while similar conceptually - are actually completely different.
Wait will synchronously block until the task completes. So the current thread is literally blocked waiting for the task to complete. As a general rule, you should use "async all the way down"; that is, don't block on async code. On my blog, I go into the details of how blocking in asynchronous code causes deadlock.
await will asynchronously wait until the task completes. This means the current method is "paused" (its state is captured) and the method returns an incomplete task to its caller. Later, when the await expression completes, the remainder of the method is scheduled as a continuation.
You also mentioned a "cooperative block", by which I assume you mean a task that you're Waiting on may execute on the waiting thread. There are situations where this can happen, but it's an optimization. There are many situations where it can't happen, like if the task is for another scheduler, or if it's already started or if it's a non-code task (such as in your code example: Wait cannot execute the Delay task inline because there's no code for it).
You may find my async / await intro helpful.
Based on what I read from different sources:
An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.
To wait for a single task to complete, you can call its Task.Wait method. A call to the Wait method blocks the calling thread until the single class instance has completed execution. The parameterless Wait() method is used to wait unconditionally until a task completes. The task simulates work by calling the Thread.Sleep method to sleep for two seconds.
This article is also a good read.
Some important facts were not given in other answers:
async/await is more complex at CIL level and thus costs memory and CPU time.
Any task can be canceled if the waiting time is unacceptable.
In the case of async/await we do not have a handler for such a task to cancel it or monitoring it.
Using Task is more flexible than async/await.
Any sync functionality can by wrapped by async.
public async Task<ActionResult> DoAsync(long id)
{
return await Task.Run(() => { return DoSync(id); } );
}
async/await generate many problems. We do not know if await statement will be reached without runtime and context debugging. If first await is not reached, everything is blocked. Sometimes even when await seems to be reached, still everything is blocked:
https://github.com/dotnet/runtime/issues/36063
I do not see why I must live with the code duplication for sync and async method or using hacks.
Conclusion: Creating Tasks manually and controlling them is much better. Handler to Task gives more control. We can monitor Tasks and manage them:
https://github.com/lsmolinski/MonitoredQueueBackgroundWorkItem
Sorry for my english.
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.
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).