Using async method indirectly (and synchronously) in a view [duplicate] - c#

I get the exception below when invoking he automagically generated async webmethods that i asked about in this post
Asynchronous operations are not allowed in this context. Page starting
an asynchronous operation has to have the Async attribute set to true
and an asynchronous operation can only be started on a page prior to
Google search results in add Async = True in the page directive but various people have noted that this makes the page 'Blocking' (which isn't true asynchronous operation). So how do i achieve asynchronous operation while calling webservice methods.

Check out this answer. I won't copy/paste the answers from there but I'll extend the discussion some.
The accepted answer is NOT the correct one. Since there is no 'EndInvoke' there will be a resource leak every time this method is invoked. See this discussion on why that's not okay.
What is suggested instead is to launch either a daemon thread or create whole different processes that reads from MSMQ and processes the long-running tasks there.

Related

Calling async method from sync method is ASP .NET web api - issue

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?
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.
No. The AppDomain is still there in this case. In ASP.NET (pre-Core), there is an ASP.NET SynchronizationContext that represents the request. await by default captures the current context and uses that to resume executing its async method.
So, when the await completes, it attempts to resume executing on the SynchronizationContext for that request. However, that request has been completed, and so it doesn't make sense to resume on that context. The resulting behavior is undefined.
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?
If you are sure you want to return early, then you should have a background service handle creating the file, not the ASP.NET service. Since you have a database already, you could use the Outbox Pattern, where you place messages in an "outbox" table as part of the same transaction as your resource creation. Then a separate background service reads the "outbox" table and writes the JSON file.

Why use async methods with Azure table storage?

I'm using Microsoft.WindowsAzure.Storage.Table and couldn't figure out what's the difference between async methods and regular methods, for example CloudTable.Execute and CloudTable.ExecuteAsync. When and why should I use each of them? Is this even related to storage design and the module I'm using or am I misunderstanding the concept of async methods (I'm new to c# and Azure)?
Edit: If I should always use async methods, why are regular methods implemented, available, and moreover used in most Azure table storage guides?
Thanks in advance!
Basically when using the CloudTable.ExecuteAsync the compiler generates a state machine in the background, so you can avoid performance bottlenecks and enhance the overall responsiveness of your application.
It's not just the table storage but any service that implements async operation should be used. We use async to off load the main thread and shift the task on the background. The main thread is ready to take more requests while background task is getting completed. Once completed it will bring back the control to the main thread. If you don't use async you get info problem called resource starvation where your request pool start growing and eventually your application hangs up .
Look into the following link and it explains in details.
Synchronous I/O antipattern

ConfigureAwait when not awaiting

I have an async method I am using to offload a few seconds' worth of fire-and-forget work so as not to slow down my page load. This work needs a bit of general setup and tidy-up; I want the (fast) setup to throw synchronously if it throws, but I don't want to force the tidy-up to run in the ASP context so I am using ConfigureAwait on the bit I am awaiting:
public Task FireAndForget()
{
DoSetup();
return FireAndForgetAfterSetup();
}
private async Task FireAndForgetAfterSetup()
{
await AFewSecondsWorthOfWork().ConfigureAwait(false);
DoTidyUp();
}
protected void btn_Click(object sender, EventArgs e)
{
FireAndForget();
}
This seems odd, because
FireAndForgetAfterSetup shouldn't really care whether or not it is being called from an ASP context, so why should it have to be the one calling ConfigureAwait?
If I change my mind and decide that btn_Click should wait for FireAndForget to complete, has it already thrown away the ASP context(?)
Can someone explain to me if I'm misunderstanding?
The ASP.NET synchronization context doesn't allow fire-and-forget work items to be kicked off from within a request. The runtime actively monitors such things and will try to generate an exception since these code patterns lead to null refs, deadlocks, AVs, and other nastiness.
If you absolutely need to kick off fire-and-forget work in ASP.NET, consider using WebBackgrounder. It integrates with the ASP.NET extensibility points that are designed to allow for this. So it won't block the active request, but keep in mind Stephen's caveat: it's not ever guaranteed to be executed at all. If you require guaranteed execution, consider a reliability mechanism like Service Bus.
If your scenario is how to execute some (relatively) long-running task during load, ASP.NET allows this scenario through the Page.RegisterAsyncTask method. Scott Hansleman describes how to use it in The Magic of using Asynchronous Methods in ASP.NET 4.5 plus an important gotcha
Essentially, you create an asynchronous method that returns Task and call:
RegisterAsyncTask(new PageAsyncTask(MyAsyncMethod));
then call Page.ExecuteRegisteredAsyncTasks to start executing all registered tasks.
Scott Hanselman does a good job (of course) of describing why using an event handler, Task or background thread is a bad idea.
This is also described in "What Not to do in ASP.NET, What to do instead" in the "Asynchronous Page Events" section
I'm not sure why he didn't post it, but my exact two questions are answered in this blog post by Stephen Cleary:
The important thing to note with this example is that each "level" of async method calls has its own context. DownloadFileButton_Click started in the UI context, and called DownloadFileAsync. DownloadFileAsync also started in the UI context, but then stepped out of its context by calling ConfigureAwait(false). The rest of DownloadFileAsync runs in the thread pool context. However, when DownloadFileAsync completes and DownloadFileButton_Click resumes, it does resume in the UI context.
A good rule of thumb is to use ConfigureAwait(false) unless you know you do need the context.
In answer to my first bullet point, yes, it's OK (encouraged!) to use ConfigureAwait(false) in library methods that know they won't use the context, because...
... in answer to my second bullet point, even if the library async method has thrown away the UI context, the calling method still has its own copy. Thus the calling method could await the library method and resume in the UI context... but it's going to deadlock when that happens.

Best practice to call ConfigureAwait for all server-side code

When you have server-side code (i.e. some ApiController) and your functions are asynchronous - so they return Task<SomeObject> - is it considered best practice that any time you await functions that you call ConfigureAwait(false)?
I had read that it is more performant since it doesn't have to switch thread contexts back to the original thread context. However, with ASP.NET Web Api, if your request is coming in on one thread, and you await some function and call ConfigureAwait(false) that could potentially put you on a different thread when you are returning the final result of your ApiController function.
I've typed up an example of what I am talking about below:
public class CustomerController : ApiController
{
public async Task<Customer> Get(int id)
{
// you are on a particular thread here
var customer = await GetCustomerAsync(id).ConfigureAwait(false);
// now you are on a different thread! will that cause problems?
return customer;
}
}
Update: ASP.NET Core does not have a SynchronizationContext. If you are on ASP.NET Core, it does not matter whether you use ConfigureAwait(false) or not.
For ASP.NET "Full" or "Classic" or whatever, the rest of this answer still applies.
Original post (for non-Core ASP.NET):
This video by the ASP.NET team has the best information on using async on ASP.NET.
I had read that it is more performant since it doesn't have to switch thread contexts back to the original thread context.
This is true with UI applications, where there is only one UI thread that you have to "sync" back to.
In ASP.NET, the situation is a bit more complex. When an async method resumes execution, it grabs a thread from the ASP.NET thread pool. If you disable the context capture using ConfigureAwait(false), then the thread just continues executing the method directly. If you do not disable the context capture, then the thread will re-enter the request context and then continue to execute the method.
So ConfigureAwait(false) does not save you a thread jump in ASP.NET; it does save you the re-entering of the request context, but this is normally very fast. ConfigureAwait(false) could be useful if you're trying to do a small amount of parallel processing of a request, but really TPL is a better fit for most of those scenarios.
However, with ASP.NET Web Api, if your request is coming in on one thread, and you await some function and call ConfigureAwait(false) that could potentially put you on a different thread when you are returning the final result of your ApiController function.
Actually, just doing an await can do that. Once your async method hits an await, the method is blocked but the thread returns to the thread pool. When the method is ready to continue, any thread is snatched from the thread pool and used to resume the method.
The only difference ConfigureAwait makes in ASP.NET is whether that thread enters the request context when resuming the method.
I have more background information in my MSDN article on SynchronizationContext and my async intro blog post.
Brief answer to your question: No. You shouldn't call ConfigureAwait(false) at the application level like that.
TL;DR version of the long answer: If you are writing a library where you don't know your consumer and don't need a synchronization context (which you shouldn't in a library I believe), you should always use ConfigureAwait(false). Otherwise, the consumers of your library may face deadlocks by consuming your asynchronous methods in a blocking fashion. This depends on the situation.
Here is a bit more detailed explanation on the importance of ConfigureAwait method (a quote from my blog post):
When you are awaiting on a method with await keyword, compiler
generates bunch of code in behalf of you. One of the purposes of this
action is to handle synchronization with the UI (or main) thread. The key
component of this feature is the SynchronizationContext.Current which
gets the synchronization context for the current thread.
SynchronizationContext.Current is populated depending on the
environment you are in. The GetAwaiter method of Task looks up for
SynchronizationContext.Current. If current synchronization context is
not null, the continuation that gets passed to that awaiter will get
posted back to that synchronization context.
When consuming a method, which uses the new asynchronous language
features, in a blocking fashion, you will end up with a deadlock if
you have an available SynchronizationContext. When you are consuming
such methods in a blocking fashion (waiting on the Task with Wait
method or taking the result directly from the Result property of the
Task), you will block the main thread at the same time. When
eventually the Task completes inside that method in the threadpool, it
is going to invoke the continuation to post back to the main thread
because SynchronizationContext.Current is available and captured. But
there is a problem here: the UI thread is blocked and you have a
deadlock!
Also, here are two great articles for you which are exactly for your question:
The Perfect Recipe to Shoot Yourself in The Foot - Ending up with a Deadlock Using the C# 5.0 Asynchronous Language Features
Asynchronous .NET Client Libraries for Your HTTP API and Awareness of async/await's Bad Effects
Finally, there is a great short video from Lucian Wischik exactly on this topic: Async library methods should consider using Task.ConfigureAwait(false).
The biggest draw back I've found with using ConfigureAwait(false) is that the thread culture is reverted to the system default. If you've configured a culture e.g ...
<system.web>
<globalization culture="en-AU" uiCulture="en-AU" />
...
and you're hosting on a server whose culture is set to en-US, then you will find before ConfigureAwait(false) is called CultureInfo.CurrentCulture will return en-AU and after you will get en-US.
i.e.
// CultureInfo.CurrentCulture ~ {en-AU}
await xxxx.ConfigureAwait(false);
// CultureInfo.CurrentCulture ~ {en-US}
If your application is doing anything which requires culture specific formatting of data, then you'll need to be mindful of this when using ConfigureAwait(false).
I have some general thoughts about the implementation of Task:
Task is disposable yet we are not supposed to use using.
ConfigureAwait was introduced in 4.5. Task was introduced in 4.0.
.NET Threads always used to flow the context (see C# via CLR book) but in the default implementation of Task.ContinueWith they do not b/c it was realised context switch is expensive and it is turned off by default.
The problem is a library developer should not care whether its clients need context flow or not hence it should not decide whether flow the context or not.
[Added later] The fact that there is no authoritative answer and proper reference and we keep fighting on this means someone has not done their job right.
I have got a few posts on the subject but my take - in addition to Tugberk's nice answer - is that you should turn all APIs asynchronous and ideally flow the context . Since you are doing async, you can simply use continuations instead of waiting so no deadlock will be cause since no wait is done in the library and you keep the flowing so the context is preserved (such as HttpContext).
Problem is when a library exposes a synchronous API but uses another asynchronous API - hence you need to use Wait()/Result in your code.

AsyncController: Interference having 2 async methods

i'm having an AsyncController that has 2 AsyncMethods.
One is called GetMessages, the other Check.
It seems, that one call blocks the other, probably because both call this.AsyncManager.OutstandingOperations.Increment();
Do they share the same AsyncManager?
What is the right way to do that?
Do i have to have 2 AsyncController to ensure that they dont get in each others way?
Update:
The code of both methods is similar to code posted here: Async operation completes, but result is not send to browser
in fact, it is the same controller, only added the Check/CheckCompleted.
sometimes, the "Check" has to get triggered so that the "GetMessages" returns
Update2: I have a waittimout of 60 seconds for both methods. I reduced one now to 5, this helps it, but i think it is just a hack.
They shouldn't block. The blocking you are observing might be due to the fact that both methods use Session and because Session is not thread safe, ASP.NET blocks access if you have two parallel requests from the same session (for example AJAX requests).
So try disabling all session for those actions by decorating them with the following attribute:
[SessionState(SessionStateBehavior.Disabled)]

Categories