I have the following async long running method inside my asp.net mvc-5 web application :-
public async Task<ScanResult> ScanAsync(string FQDN)
{
// sample of the operation i am doing
var c = await context.SingleOrDefaultAsync(a=>a.id == 1);
var list = await context.Employees.ToListAsync();
await context.SaveChangesAsync();
//etc..
}
and i am using Hangfire tool which support running background jobs to call this async method on timely basis, but un-fortuntly the hangefire tool does not support calling async methods directly . so to overcome this problem i created a sync version of the above method , as follow:-
public void Scan()
{
ScanAsync("test").Wait();
}
then from the HangFire scheduler i am calling the sync method as follow:-
RecurringJob.AddOrUpdate(() => ss.Scan(), Cron.Minutely);
so i know that using .Wait() will mainly occupy the iis thread during the method execution ,, but as i mentioned i need to do it in this way as i can not directly call an async TASK inside the hangefire scheduler .
so what will happen when i use .Wait() to call the async method ?, will the whole method's operations be done in a sync way ? for example as shown above i have three async operations inside the ScanAsync() ;SingleOrDefualtAsync,ToListAsync & SaveChangesAsync, so will they be executed in sync way because i am calling the ScanAsync method using .wait() ?
so what will happen when i use .Wait() to call the async method ?,
will the whole method's operations be done in a sync way ? for example
as shown above i have three async operations inside the ScanAsync()
;SingleOrDefualtAsync,ToListAsync & SaveChangesAsync, so will they be
executed in sync way because i am calling the ScanAsync method using
.wait() ?
The methods querying the database will still be executed asynchronously, but the fact that you're calling Wait means that even though you're releasing the thread, it wont return to the ASP.NET ThreadPool as you're halting it.
This is also a potential for deadlocks, as ASP.NET has a custom synchronization context which makes sure the context of the request is availiable when in a continuation of an async call.
I would recommend that instead, you'd use the synchronous API provided by entity-framework, as you won't actually be enjoying the scalability one can get from asynchronous calls.
Edit:
In the comments, you asked:
As i am currently doing with hangefire eliminate the async effect ? if yes then will it be better to use sync methods instead ? or using sync or async with hangeffire will be exactly the same
First, you have to understand what the benefits of async are. You don't do it because it's cool, you do it because it serves a purpose. What is that purpose? Being able to scale under load. How does it do that? When you await an async method, control is yielded back to the caller. For example, you have an incoming request, you query you database. You can either sit there and wait for the query to finish, or you can re-use that thread to serve more incomong requests. That's the true power.
If you don't actually plan on receiving a decent amount of requests (such that you'll starve the thread-pool), you won't actually see any benefit from async. Currently, the way you've implemented it, you won't see any of those benefits because you're blocking the async calls. All you'll see, possibly, are deadlocks.
This very much depends on the way HangFire is implemented. If it just queuing tasks to be invoked in ThreadPool the only effect will be, that one of your threads will be blocked until the request is ended. However if there is a custom SynchronizationContext this can lead to a serious deadlock.
Consider, if you really want to wait for your scheduled job to be done. Maybe all you want is just a fire and forget pattern. This way your method will be like:
public void Scan()
{
ScanAsync("test"); // smoothly ignore the task
}
If you do need to wait, you can instead try using async void method:
public async void Scan()
{
await ScanAsync("test");
DoSomeOtherJob();
}
There are many controversies about using async void as you cannot wait for this method to end, nor you can handle possible errors.
However, in event driven application this can be the only way. For more informations you can refer to: Async Void, ASP.Net, and Count of Outstanding Operations
Related
I'm trying to find out which approach is better let's say we have a button, after user clicks it we perform 1. Send a async request using httpClient
2. Some heavy synchronous staff like computations and saving data to a database.
Like that:
button1.Click += async(sender, e) =>
{
bool a = await Task.Run(async () => { return await MyTask1();});
}
async Task<bool> MyTask1()
{
await new HttpClient().GetAsync("https://www.webpage.com");
DoHeavyStuffFor5minutes();
return true;
}
button2.Click += async(sender, e) =>
{
bool a = await MyTask2();
}
async Task<bool> MyTask2()
{
await new HttpClient().GetAsync("https://www.webpage.com").ConfigureAwait(false);
DoHeavyStuffFor5minutes();
}
From what i understand GetAsync does not block my UI thread because underneath it uses a method which make it runs on different thread perhaps Task.Run or any other method that allows that.
But DoHeavyStuffFor5Minutes will block my UI because it will get called on the caller SynchornizationContext.
So i read that using ConfigureAwait(false) will make code after GetAsync do not run on the same SynchornizationContext as the caller. My question is, which approach is better first or the second one?
There is no need to execute HttpClient.GetAsync on a background thread using Task.Run since the HTTP request is truly asynchronous by nature so in this case your second approach is better that the first one.
When the Task returned by GetAsync has eventually finished, the remainder or MyTask2() will be executed on a thread pool thread assuming you opt out of capturing the context by calling ConfigureAwait(false).
Note however that ConfigureAwait(false) does not guarantee that the callback or remainer won't be run in the original context in all cases.
From Stephen Toub's blog post:
Does ConfigureAwait(false) guarantee the callback won’t be run in the original context?
"No. It guarantees it won’t be queued back to the original contex...but that doesn’t mean the code after an await task.ConfigureAwait(false) won’t still run in the original context. That’s because awaits on already-completed awaitables just keep running past the await synchronously rather than forcing anything to be queued back. So, if you await a task that’s already completed by the time it’s awaited, regardless of whether you used ConfigureAwait(false), the code immediately after this will continue to execute on the current thread in whatever context is still current."
So you might want to off-load DoHeavysTuffFor5minutes, which I assume is a CPU-bound and potentially long-running operation, to a background thread using Task.Run to be on the safe side. At least in the general case.
Also note that a method that is named *Async and returns a Task or Task<T> might still block the calling thread depending on its implementation. In general, this may be a reason to use your first approach of a calling both methods on a background thread in order to avoid blocking the UI thread. If you however use well-implemented APIs, such as HttpClient, this isn't an issue though.
I've been trying to understand async/await and Task in C# but have been failing spectacularly despite watching youtube videos, reading documentation and following a pluralsight course.
I was hoping someone might be able to help answer these slightly abstract questions to help my brain out.
1.Why do they say that async/await enables an 'asynchonrous' method when the async keyword on it's own does nothing and the await keyword adds a suspension point? Isn't adding a suspension point forcing the method to act synchronously, i.e. finish the task marked by the await before moving on.
2.Apparently you are not supposed to use async void except for event handlers, so how do you call an async method normally? It seems that in order to call an async method by using the await keyword, the method/class that is calling it itself needs to be marked as async. All the examples I've seen have 'initiated' an async void method with an event handler. How would you 'escape' this wrapping of async/await to run the method?
3.
public async Task SaveScreenshot(string filename, IWebDriver driver)
{
var screenshot = driver.TakeScreenshot();
await Task.Run(() =>
{
Thread.Sleep(2000);
screenshot.SaveAsFile(filename, ScreenshotImageFormat.Bmp);
Console.WriteLine("Screenshot saved");
});
Console.WriteLine("End of method");
}
Relating back to 1. this looks like a synchronous method. Execution pauses when it gets to Task.Run, therefore Console.WriteLine("End of method"); will not be executed until the task is finished. Maybe the whole method itself will be executed asynchronously at the point it is triggered in the code? But relating back to 2, you need to call this with an await otherwise you get the message 'Because this call is not awaited..' therefore adding an await will cause that execution point to be synchronous and so on and so.
Any help understanding this would be much appreciated.
Isn't adding a suspension point forcing the method to act synchronously, i.e. finish the task marked by the await before moving on.
No, the word you're thinking of is "sequential", not "synchronous". await results in asynchronous sequential code. "Sequential" meaning "one at a time"; "synchronous" meaning "blocking until completed".
how do you call an async method normally?
Using await.
How would you 'escape' this wrapping of async/await to run the method?
Ideally, you don't. You go async all the way. Modern frameworks (including ASP.NET MVC, Azure Functions / WebJobs, NUnit / xUnit / MSTest, etc) all allow you to have entry points that return Task. Less-modern frameworks (including WinForms, WPF, Xamarin Forms, ASP.NET WebForms, etc) all allow async void entry points.
So, ideally you do not call asynchronous code from synchronous code. This makes sense if you think about what asynchronous code is: the entire point of it is to not block the calling thread, so if you block the calling thread on asynchronous code, then you lose all the benefits of asynchronous code in the first place.
That said, there are rare situations where you do need to treat the code synchronously. E.g., if you are in the middle of a transition to async, or if you are constrained by a library/framework that is forcing your code to be synchronous and won't work with async void. In that case, you can employ one of the hacks in my article on brownfield async.
Your understanding is pretty good :). The main point you seem to be missing is that "asynchronous" methods in .NET mean methods that can stop execution without blocking the calling thread.
As you pointed out in (1), the async keyword basically enables the use of await and requires the return type to be void or Task/Task<T>. await just instructs the current method to suspend execution until the task is complete.
What you are missing here is that it suspends just the current method. It does not block the thread the method was executing on. This is important in cases like the UI thread of a WPF application. Suspend method execution and everything keeps running, block the thread and the application stops responding.
You usually want your async calls to go all the way to the top (like an event handler), this allows the most flexibility and prevents deadlock situations. However; you can wait for a Task returning method to complete with Wait:
someAsyncMethod.Wait()
Or get the return value:
var result = someAsyncMethod.Result;
Note that both of these are synchronous and block the calling thread. Doing this can cause deadlock if the async task is waiting for some other work on the calling thread to complete.
The above should answer your question in (3); the method itself appears to execute synchronously (this is the magic of await/async) but the task doesn't block the calling thread.
It is asynchronous because you don't have to wait the method to return. In your code, you may call the async method and save the task in a variable. Continue doing something else. Later, when the method result is needed, you await the response (task).
// Synchronous method.
static void Main(string[] args)
{
// Call async methods, but don't await them until needed.
Task<string> task1 = DoAsync();
Task<string> task2 = DoAsync();
Task<string> task3 = DoAsync();
// Do other stuff.
// Now, it is time to await the async methods to finish.
Task.WaitAll(task1, task2, task3);
// Do something with the results.
Console.WriteLine(task1.Result);
Console.ReadKey();
}
private static async Task<string> DoAsync()
{
Console.WriteLine("Started");
await Task.Delay(3000);
Console.WriteLine("Finished");
return "Success";
}
// Output:
// Started
// Started
// Started
// Finished
// Finished
// Finished
// Success
I'm trying to create a class that has synchronous methods and calls some other library methods which are asynchronous. For that reason I use Task.Result to wait for the async operation to finish. My methods are called by WPF app in synchronous way. This leads to a deadlock. I know that the best way is to make all my methods asynchronous but my situation requires them to be synchronous. From the other hand they use other library which is asynchronous.
My question is: How can I avoid the deadlock in such situation?
Steps to reproduce:
User hits a button in the app (method Button1_OnClick)
This method creates an instance of IPlugin and then calls its method RequestSomething()
This method then calls async library this way: asyncTarget.MethodFromAsyncLibrary("HelloFromPlugin").Result
The library calls back its method NotifyNewValueProgressAsync()
NotifyNewValueProgressAsync() delegates the call back to the WPF application
Since the UI context is blocked by this line asyncTarget.MethodFromAsyncLibrary("HelloFromPlugin").Result the callback in step 5 leads to a deadlock.
See code example below and related comments:
public class SyncAdapterPlugin : IPlugin, IProgressAsyncHandler
{
//Constructor and fields are omitted here
//This method is called from UI context by WPF application and it delegates synchronous call to asynchronous method
string IPlugin.RequestSomething()
{
//In order to be able to run the callback I need to capture current UI context
_context = TaskScheduler.FromCurrentSynchronizationContext();
var asyncTarget = new ClassFromMyLibrary1(this);
var resultFromAsyncLibrary = asyncTarget.MethodFromAsyncLibrary("HelloFromPlugin").Result; //Deadlock here!
return resultFromAsyncLibrary;
}
//This method does opposite, it delegates asynchronous callback to synchronous
async Task<bool> IProgressAsyncHandler.NotifyNewValueProgressAsync(string message)
{
//NotifyNewValueProgress method is implemented by WPF application and will update UI elements.
//That's why it's needed to run the callback on captured UI context.
Func<bool> work = () => _syncProgressHandler.NotifyNewValueProgress(message);
if (_context != null)
{
return await
Task.Factory.StartNew(work, CancellationToken.None, TaskCreationOptions.None, _context)
.ConfigureAwait(false);
}
return work();
}
}
Complete code example is here https://dotnetfiddle.net/i48sRc.
FYI, Some background on this issue you can also find in this SO question.
The plugin framework is fundamentally flawed. In particular, it requires a synchronous RequestSomething that expects to be able to call NotifyNewValueProgressAsync to update the UI. However, it's not possible to display a UI update while the UI thread is running a synchronous method.
This forces you to use one of the most dangerous and evil sync-over-async hacks: the nested message loop hack (as briefly described in my article on brownfield async). Since this is a WPF app, you'd use a nested dispatcher frame. The main pain with this hack is that it introduces reentrancy across your entire UI layer, which is the most subtle and difficult kind of concurrency problem.
By definition a synchronous method isn't going to be asynchronous. You will need to wrap the calls to the synchronous methods from the UI in a Task using TAP and await them there while making the method you await from asynchronous.
Async method:
public void Main(){
await Asynctask1;
DoSomething();
}
public async Task AsyncTask1(){
//Async logic here
}
Sync method:
public void Main(){
SyncMethod1();
DoSomething();
}
I think I'm missing something here. Assuming that SyncMethod1() and Asynctask1() both do the same thing, aren't these 2 constructs in the end the same result, namely that DoSomething() doesn't start until the method before finishes?
namely that DoSomething() doesn't start until the method before finishes?
There's a difference between asynchrony and sequential. When you always await your asynchronous methods immediately, you end up with asynchronous sequential code, which at first glance does appear to behave similarly to synchronous sequential code. (On a side note, this similarity is the entire point of the async/await keywords). However, there's one important difference.
Let's say the operation is some I/O thing, like getting an HTTP resource. SyncMethod1 will do the HTTP get synchronously; that is, it sends out the HTTP request and then blocks the thread until it gets the HTTP response. AsyncTask1 will do the HTTP get asynchronously; that is, it sends out the HTTP request and then returns an incomplete Task. Later, when the HTTP request comes in, the AsyncTask1 method will resume and complete the returned Task, and the code after the await is run (i.e., DoSomething).
The asynchronous way is more complicated but has one key advantage: it does not block a thread. So, UI threads are freed to enable a responsive UI and ASP.NET threads are freed to handle other requests.
I have an async intro on my blog that may help as you learn.
In the case you have outlined there is no practical difference as you immeadiately wait for the asynchronous method to complete before moving on to the next.
However, if you restructured your code something like this you might realize the power of asynchronous programming:
public async void Main() {
Task performTask = AsyncTask1();
//This method can continue without having to wait for AsyncTask1 to complete
DoSomething();
//Here we await the AsyncTask1 because perhaps other code further
//down is depending on it
await performTask;
}
I'm not sure if this is a SignalR issue or an async/await issue. When my client app (WPF) starts up, it does some initialisation:-
public async void Initialise()
{
// Get data from the server - async, as it may be long-running.
var data = await _hubProxy.Invoke<FooData>("Method1");
_dataProcessor.ProcessData(data);
}
The _dataProcessor is a helper class that does some stuff with the data passed to it, then at some point calls a different server method using a line similar to:-
var moreData = _hubProxy.Invoke<BarData>("Method2").Result;
None of the code in the helper class is async.
The first server invoke (in Initialise()) works fine - it gets back the data and passes it to the helper class. This proceeds without issue until its invoke - it gets called but never returns, and the thread never proceeds past this line. I've put a breakpoint in the server method and can confirm that it is being called and returning a value, but for some reason this is not getting back to the client.
The strange thing is, if I take out the async/await keywords in the Initialise() method, everything works fine. What am I doing wrong? Why would these keywords affect the synchronous code in the helper class?
(I realise you shouldn't normally use async void, but as the Initialise() method is "fire and forget", I thought it was okay in this scenario).
This line causes a deadlock on the UI thread:
var moreData = _hubProxy.Invoke<BarData>("Method2").Result;
Make ProcessData an async method and await _hubProxy.Invoke inside it:
var moreData = await _hubProxy.Invoke<BarData>("Method2");
Then, await _dataProcessor.ProcessData in your Initialise:
await _dataProcessor.ProcessData(data);
Make sure you don't use .Result or .Wait anywhere else.
Another way of solving it is just this:
public async void Initialise()
{
// Get data from the server - async, as it may be long-running.
var data = await _hubProxy.Invoke<FooData>("Method1").ConfigureAwait(false);
_dataProcessor.ProcessData(data);
}
Note ConfigureAwait(false). In this case the continuation after await will happen on a non-UI thread. This will eliminate the deadlock, but this is not an ideal solution, rather a workaround. Moreover, your logic may require the continuation on the UI thread, for UI access or some thread-safety concerns.
The best solution would be to use both ConfigureAwait(false) (if possible) and avoid blocking with .Result or .Wait, at the same time.