I have a Windows form GUI that polls a database server every X minutes. If it finds data it posts the data to an HTTP API. Since I am using a Timer to accomplish the polling do I still need to make use of asynchronous code such as this when calling the API?
Task.Run(async () =>
{
// Call HTTP code here
}).Wait();
I would like the GUI to remain responsive and not lock up.
I am new to asynchronous development in .NET and still not sure how to implement it properly.
Since I am using a Timer to accomplish the polling do I still need to make use of asynchronous code such as this when calling the API?
If you're using System.Threading.Timer or System.Timers.Timer then you dont have to use an async api to keep your GUI responsive as these will invoke the delegate passed to them on a ThreadPool thread. Specifically in your example, you're mistakenly using Wait which waits synchronously on the new thread you're creating, which makes no sense.
If the only thing your delegate is doing is IO bound calls, such as a HTTP request or an async database call (for example, EF exposes async endpoints) then you dont need the extra thread to keep you UI responsive.
Here's an example using Task.Delay (which internally uses a timer) which is purely async:
public async Task PoolAndWaitAsync(int timeToWait)
{
var httpClient = new HttpClient();
while (true)
{
// Query database
var data = await MyDatabase.QueryAsync(..);
if (data != null)
{
var response = await httpClient.PostAsync(..);
}
await Task.Delay(timeToWait);
}
}
It depends on whether you make your HTTP Code asynchronous. Provided you use an async API within that event handler, it should be fine to not wrap in a separate Task.Run.
The Task object iteself performs in async operations. Servy is right. You have to remove the .Wait().
But as long as you want to populate some controls within your async method, you have to be sure to be thread safe.
Cheers, Martin
Related
I was reading a chapter about the await and async keywords in my C# book.
It was mainly explaining these kinds of method calls, where the caller uses the await keyword to wait for the called method to finish.
In this simple example I see no advantage but more importantly no difference in these 3 calls. Can anyone explain what difference it makes to the flow of the application? Is it only useful when the calling thread is the main GUI thread?
static async Task Main(string[] args)
{
WriteText();
await WriteTextAsync();
WriteTextAsync().Wait();
}
static void WriteText()
{
Thread.Sleep(3_000);
Console.WriteLine("Hello");
}
static async Task WriteTextAsync()
{
await Task.Run(() =>
{
Thread.Sleep(3_000);
Console.WriteLine("Hello");
});
}
Ps: If the calling thread of the method is waiting for the method to finish anyway it might as well be a normal call?
As my understanding about your question is
If the program waits for the response in await WriteTextAsync() line then what will be the benifit?
For client applications, such as Windows Store, Windows desktop and Windows Phone apps, the primary benefit of async is responsiveness. These types of apps use async chiefly to keep the UI responsive. For server applications, the primary benefit of async is scalability.
I will try to explain from the web-app point of view.
Suppose you have a web application depends on external resources like database call, when a client initiates a request ASP.NET takes one of its thread pool threads and assigns it to that request. Because it’s written synchronously, the request handler will call that external resource synchronously. This blocks the request thread until the call to the external resource returns. Figure 1 illustrates a thread pool with two threads, one of which is blocked waiting for an external resource.
Figure 1 Waiting Synchronously for an External Resource
Now if third client requests at the same time then there is no thread in thread pool available to assign the third request.
In asynchronous call, thread will not be stuck rather will be released and comes back to the thread pool which will facilitates to serve the third call.
When request server activities ends linke database call ends then SynchronizationContext resumes that call and returns repose to client.
Bellow image in simple analogy of aync call
There is lot of things happens under the hood. I wrote this maily from Async Programming : Introduction to Async/Await on ASP.NET and my understanding. It is highly recommended to have clear understanding before using async-wait.
I'll be referring to:
//Call 1
WriteText();
//Call 2
await WriteTextAsync();
//Call 3
WriteTextAsync().Wait();
The first call doesn't have any problem, if what you want to do is a synchronous wait. In a Console application, this is quite normal.
The problem arises in programs with a UI or those that require the best use of CPU resources, the most common case being web applications.
Call 2, using await performs an asynchronous wait for the result of WriteTextAsync. In its own, that's fine and what's considered normal. However, WriteTextAsync is a very good example of something you should never do:
static async Task WriteTextAsync()
{
// Let's create a Thread
await Task.Run(() =>
{
// just to block it completely, having it do nothing useful
Thread.Sleep(3_000);
Console.WriteLine("Hello");
});
}
Rather, the author should have used:
static async Task WriteTextAsync()
{
// Let's *not* create a new thread
await Task.Delay(3_000);
Console.WriteLine("Hello");
}
Maybe they were to point this out further down the line, but you didn't give us the book name to know this.
Call number 3 is what you would have to do when the calling method cannot be an async one and you have to call an async method, so:
// Think that for some reason you cannot change the signature,
// like in the case of an interface, and an async void would make your code
// never complete correctly
static void Main(string[] args)
{
//Call 3
WriteTextAsync().Wait();
}
Overall, I would suggest you to find a better book. Examples are easier to understand when asynchronous code is actually required.
When you say WriteText(), WriteText() will block your current thread until it completes, as it is synchronous.
When you say await WriteTextAsync(), you will spawn a new thread and you will not block computations that do not depend on the result of WriteTextAsync().
EDIT: According to Microsoft Docs When you say await WriteTextAsync(), the compiler schedules the rest of Main() for execution after WriteTextAsync() completes. Then the control is supposed to be returned to the caller of the async method. But who is the caller of Main()? As it turns out, there is no async Main() - it is actually the same synchronous Main() - and it's just syntactical sugar for not writing .Wait() inside it. So in this case this call is equivalent to WriteTextAsync().Wait()!
Finally, when you say WriteTextAsync().Wait(), you block your current thread again and wait for the result of WriteTextAsync().
This is the Github Repository which I am using
https://github.com/ilkerulutas/BinanceSdk
The code is working fine on a console application but it takes too much time to get a response in windows form application.
//Async Method
public async Task<TimeResponse> Time()
{
return await SendRequest<TimeResponse>("time", ApiVersion.Version1, ApiMethodType.None, HttpMethod.Get);
}
//Sync Method
public TimeResponse TimeSync() => Time().Result;
I am calling both but async method is giving status WaitingForActivation and Sync method is taking too much time to get response.
I am calling these 2 methods as
var timeResponseAsync = publicRestClient.Time(); //For Async
var timeResponseSync1 = publicRestClient.TimeSync(); // For Sync
You are deadlocking your UI thread.
My guess would be that you are calling TimeSync() which then calls a Task.Result, which blocks the UI thread until the Task returned from Time() is finished.
As you have an await inside Time() which starts on the UI thread, the async callback once the request is complete will be scheduled to happen on the UI thread, but this UI thread is already blocked by waiting for the Task.Result. So therefore you are in a deadlocked situation.
Could you show how you are using TimeSync and why are you using a Sync method which then uses an async method. To properly fix it, you need to make everything up the call chain async and await the result!
One patch fix you can try is to do (this may or may not work, best case scenario it will still block the UI for the duration of the call):
public TimeResponse TimeSync() => Task.Factory.StartNew(() => Time()).Result;
Lets say im within an ASP.NET application, WCF or web API, part of this applications job to is contact a 3rd party over the way. Id like to do this asynchronously or rather non blocking so that the thread pool doesnt get starved. However i dont want to change all my code in the service only the bit that makes the web call.
Here is some code i have written:
public string GetSomeData()
{
Task<string> stuff = CallApiAsync();
return stuff.result; //does this block here?
}
private async Task<string> CallApiasync()
{
using (var httpClient = new HttpClient())
{
string response = await httpClient.GetStringAsync(Util.EndPoint).ConfigureAwait(false);
return response;
}
}
I thought the idea was as follows but please correct any misconceptions.
The caller of CallApi can call the method and when it hits await there is a Task created which represents some work to be done asynchronously but that will take some time. At this point the thread reaches an await returns to the thread pool to do something else ie handle a different request. Once the Task completes the await line wakes up and the code continues from there as if it was synchronous.
If this is the case why do i need to return a Task from my apimethod. The caller seems to have to call stuff.Result which implies that the task may not have finished and calling result could block ? Note i don't want to make the calling method async too as then the method that calls that would need to be async etc etc.
What is the order of event here in my code?
One other question is why did i need to set configureAwait to false? otherwise everything hangs.
Id like to do this asynchronously or rather non blocking so that the thread pool doesnt get starved. However i dont want to change all my code in the service only the bit that makes the web call.
That's not possible. In order to be truly asynchronous, you must allow async to "grow" through the code as far as it needs to. What you're trying to do is block on an asynchronous call, which won't give you any benefit (you're freeing up a thread by using async, but then you're turning around and consuming a thread by using Result).
At this point the thread reaches an await returns to the thread pool to do something else ie handle a different request.
Not quite. When an async method hits an await, it returns an incomplete Task to its caller. If the caller, in turn, awaits that task, then it returns an incomplete Task to its caller, etc. When the ASP.NET runtime receives an incomplete Task from your action/service method/whatever, then it releases the thread to the thread pool.
So, you do have to go "async all the way" to see the real benefit of async.
I have an async intro on my blog if you want a more gentle introduction, as well as an MSDN article on async best practices (one of which is: async all the way). I also have a blog post that describes the deadlock you were seeing.
The compiler handles a lot of the magic behind the async pattern for you, but syntactically, you have to tell it what you want it to do by providing a method prototype that says "ok, this is an asynchronous operation that can be awaited."
For this to happen, your method must return a Task or Task<T>.
Any Task can be awaited.
You should be VERY careful when using .Result and .Wait(), as they can block in some very unexpected circumstances, because the runtime may decide to execute your method synchronously.
You should say:
await CallApiAsync();
or, to actually take advantage of it:
Task stuff = CallApiAsync();
//More code that can happen independetly of "stuff"
await stuff;
In order to do that, your GetSomeData() function must also be marked as async, but it doesn't have to, itself, return a Task.
Finished copy of a working async version of your code:
public async string GetSomeData()
{
Task stuff = CallApiAsync();
return await stuff;
}
private async Task<string> CallApiasync()
{
using (var httpClient = new HttpClient())
{
string response = await httpClient.GetStringAsync(Util.EndPoint).ConfigureAwait(false);
return response;
}
}
Honestly, if that's all the CallApiAsync function is ever going to do, you may as well inline it, though.
I have a method in ASP.NET application, that consumes quite a lot of time to complete. A call to this method might occur up to 3 times during one user request, depending on the cache state and parameters that user provides. Each call takes about 1-2 seconds to complete. The method itself is synchronous call to the service and there is no possibility to override the implementation.
So the synchronous call to the service looks something like the following:
public OutputModel Calculate(InputModel input)
{
// do some stuff
return Service.LongRunningCall(input);
}
And the usage of the method is (note, that call of method may happen more than once):
private void MakeRequest()
{
// a lot of other stuff: preparing requests, sending/processing other requests, etc.
var myOutput = Calculate(myInput);
// stuff again
}
I tried to change the implementation from my side to provide simultaneous work of this method, and here is what I came to so far.
public async Task<OutputModel> CalculateAsync(InputModel input)
{
return await Task.Run(() =>
{
return Calculate(input);
});
}
Usage (part of "do other stuff" code runs simultaneously with the call to service):
private async Task MakeRequest()
{
// do some stuff
var task = CalculateAsync(myInput);
// do other stuff
var myOutput = await task;
// some more stuff
}
My question: Do I use the right approach to speed up the execution in ASP.NET application or am I doing unnecessary job trying to run synchronous code asynchronously?
Can anyone explain why the second approach is not an option in ASP.NET (if it is really not)?
Also, if such approach is applicable, do I need to call such method asynchronously if it is the only call we might perform at the moment (I have such case, when no other stuff there is to do while waiting for completion)?
Most of the articles in the net on this topic covers using async-await approach with the code, that already provides awaitable methods, but that's not my case. Here is the nice article describing my case, which doesn't describe the situation of parallel calls, declining the option to wrap sync call, but in my opinion my situation is exactly the occasion to do it.
It's important to make a distinction between two different types of concurrency. Asynchronous concurrency is when you have multiple asynchronous operations in flight (and since each operation is asynchronous, none of them are actually using a thread). Parallel concurrency is when you have multiple threads each doing a separate operation.
The first thing to do is re-evaluate this assumption:
The method itself is synchronous call to the service and there is no possibility to override the implementation.
If your "service" is a web service or anything else that is I/O-bound, then the best solution is to write an asynchronous API for it.
I'll proceed with the assumption that your "service" is a CPU-bound operation that must execute on the same machine as the web server.
If that's the case, then the next thing to evaluate is another assumption:
I need the request to execute faster.
Are you absolutely sure that's what you need to do? Are there any front-end changes you can make instead - e.g., start the request and allow the user to do other work while it's processing?
I'll proceed with the assumption that yes, you really do need to make the individual request execute faster.
In this case, you'll need to execute parallel code on your web server. This is most definitely not recommended in general because the parallel code will be using threads that ASP.NET may need to handle other requests, and by removing/adding threads it will throw the ASP.NET threadpool heuristics off. So, this decision does have an impact on your entire server.
When you use parallel code on ASP.NET, you are making the decision to really limit the scalability of your web app. You also may see a fair amount of thread churn, especially if your requests are bursty at all. I recommend only using parallel code on ASP.NET if you know that the number of simultaneous users will be quite low (i.e., not a public server).
So, if you get this far, and you're sure you want to do parallel processing on ASP.NET, then you have a couple of options.
One of the easier methods is to use Task.Run, very similar to your existing code. However, I do not recommend implementing a CalculateAsync method since that implies the processing is asynchronous (which it is not). Instead, use Task.Run at the point of the call:
private async Task MakeRequest()
{
// do some stuff
var task = Task.Run(() => Calculate(myInput));
// do other stuff
var myOutput = await task;
// some more stuff
}
Alternatively, if it works well with your code, you can use the Parallel type, i.e., Parallel.For, Parallel.ForEach, or Parallel.Invoke. The advantage to the Parallel code is that the request thread is used as one of the parallel threads, and then resumes executing in the thread context (there's less context switching than the async example):
private void MakeRequest()
{
Parallel.Invoke(() => Calculate(myInput1),
() => Calculate(myInput2),
() => Calculate(myInput3));
}
I do not recommend using Parallel LINQ (PLINQ) on ASP.NET at all.
I found that the following code can convert a Task to always run asynchronously
private static async Task<T> ForceAsync<T>(Func<Task<T>> func)
{
await Task.Yield();
return await func();
}
and I have used it in the following manner
await ForceAsync(() => AsyncTaskWithNoAwaits())
This will execute any Task asynchronously so you can combine them in WhenAll, WhenAny scenarios and other uses.
You could also simply add the Task.Yield() as the first line of your called code.
this is probably the easiest generic way in your case
return await new Task(
new Action(
delegate () {
// put your synchronous code here
}
)
);
I have such question. For example I create dynamically custom userControl using mvvm pattern. So I've sended a command to create an userControl. So creation looks like
private async Task<bool> OnAddUserControl1(List<ALV_VM_ADWERT> control)
{
try
{
_cancellationTokenSource = new CancellationTokenSource();
var userControl = _userControlsContainer.CreateUserControl1(control);
var task1 = Task.Factory.StartNew(() =>
{
userControl.ViewModel.InOperationEvent += OnUsercontrolInOperationChanged;
userControl.ViewModel.ValueTypeChangedEvent += OnValueTypeChanged;
userControl.ViewModel.SetExpandableName += OnSetExpandableName;
}, _cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext());
var task2 = Task.Factory.StartNew(() => FinalCreatingStep(userControl, control[0].RAUMNAME.Trim()), _cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext());
await Task.WhenAll(task1, task2);
return true;
}
catch (Exception)
{
return false;
}
}
and my question is - does it make sence to create child tasks, or it is better to have code without child tasks? And if the answer is yes, then should I make all methods async? If not, what methods I should not make async?
Do those event subscriptions really need to be asynchronous? You may be trying too hard to use asynchronous code.
The user control constructor is usually the most time consuming part and must be done on the UI thread. Asynchronous operations are generally only required when some form of IO or processing is involed;
Reading Files
Writing Files
Processing large data sets
Crossing the process boundary to talk to a server or connect device
In short, an asynchronous task is probably overkill here.
Does it make sence to create child tasks, or it is better to have code without child tasks?
It is depending on your requirements. If your UI will blocked (Freeze) for long time you have to create a child task, otherwise not!
And if the answer is yes, then should I make all methods async? If not, what methods I should not make async?
Here it is also depending on your requirements and your .Net Version. If you are using .NET 4.5 the easiest way to do that with Async await. If you are using .Net 3.5 than just use Task. If .Net 2 use BackgorundWorker else use Thread class. ONLY Asynchrony methods must get the word async. Other methods you do not have to change them. In other words only the method which blocked the UI.
Your current code doesn't make any sense.
The point of async code in a UI application is responsiveness - i.e., moving long-running operations off the UI thread. As #Gusdor pointed out, most of the use cases for async are I/O-based (or event-based) operations, where you don't want to block the UI thread just to wait for some result. Another use case is when you have some CPU-bound work to do, but you don't want to tie up the UI thread; in this case, you can use Task.Run.
But in your code, you're calling StartNew with TaskScheduler.FromCurrentSynchronizationContext, which means your "child" tasks are going to execute on the UI thread. So your OnAddUserControl1 is just starting tasks which will run on the same thread and asynchronously waiting for them to complete. This is a very complex way of doing nothing.
While we're on the subject of StartNew, there are a number of other problems:
The code is passing a CancellationToken without ever observing it in the delegate.
The code is specifying AttachedToParent which is incorrect for await-compatible tasks.
As mentioned above, the code is passing a TaskScheduler which will run the delegate right back on the UI thread.
If you need to use background (thread pool) tasks, you should use Task.Run instead of Task.Factory.StartNew; I go into more detail on my blog.
So for this example, it doesn't make sense to use async or await at all.
The best way to start using async is to identify the I/O-bound (or event-driven) parts first (e.g., HTTP requests, database calls), make them async, and then work your way up the call stack.