I have a ASP .NET web api 2 application, and I'm trying to call asnyc method from sync method and meanwhile I encountered some issues. If I just call the method as a regular method the body after delay doesn't get executed, if I call it with Task.Run() it gets executed
public void CallingMethod(MethodExecutionArgs args)
{
//do something with the args
System.Diagnostics.Debug.WriteLine("BEFORE ");
WriteFileToDiskAsync(args); // If I run only this, I never see "WriteFile() - AFTER delay" in the output
Task.Run(async () => await WriteFileToDiskAsync(args)); // this executes the entire async method
System.Diagnostics.Debug.WriteLine($"Finally written from sync method");
}
private async Task<bool> WriteFileToDiskAsync(dynamic file)
{
System.Diagnostics.Debug.WriteLine("Before delay inside async");
await Task.Delay(3000);
System.Diagnostics.Debug.WriteLine("WriteFile() - AFTER delay");
}
Result: I always see the lines written from CallingMethod, but when I call the async method like a regular method, I only see the "Before delay inside async", If I call it with Task.Run() it see both lines from the async method.
Question1: Can someone explain this behavior, why doesn't the async method execute fully? Does it have something to do with what Stephen Cleary says: If you lose your AppDomain for any reason, that in-progress work is lost.
I read these articles but can't figure out why is this happening:
- How to call asynchronous method from synchronous method in C#?
- Fire and forget async method in asp.net mvc
- C# async/await with/without awaiting (fire and forget)
- https://blog.stephencleary.com/2012/12/returning-early-from-aspnet-requests.html According to most articles what I'm trying to do is not recommended (among other things the exceptions from the async method would get swallowed) but in my case I already have the information that I need to generate the response and what is done in the Async method doesn't concern the client at all...
Context: What I'm trying to achieve is, on a existing API route that creates a X Resource (saves it in a database), after the X resource is created, I want to asynchronously call a method that will Create a json file with some information from that X Resource and save it in a filesystem. But even if the writing of the file fails, I want to return a successful response to the client (because his request was to actually save the X Resource - which succeeded) he doesn't care about Creating external file in XYZ filesystem.
Question2: What would you say is the best practice to achieve what I described above, considering all the existing methods chained in the CreateResource route are sync?
asyncmethods from non-asyncmethods. What's stopping you from markingCallingMethodasasyncand having it return a Task?CallingMethodis sync and it is called by 60+ different methods which are called by N methods... And if I just make CallingMethod async and call it regularly from the sync method I would get the same behaviour as desribed aboveasyncgrows throughout the app. It's not too hard to to refactor the apps. Just make sure all your async calls are awaited, and that they're being called from methods that are marked as async and return a Task or Task<T>. It's a straightfoward refactor in most cases.