I want to call a method from a web service.
I think what happen in sync mode is
var obj = new SalesOrder.CustServicesSoapClient();
obj.AddProduct(txtName.Text, txtColor.Text)
wait for response and then
ResSpan.innerHTML="foo";
but in async mode:
var obj = new SalesOrder.CustServicesSoapClient();
obj.AddProductAsync(txtName.Text, txtColor.Text)
next line run independent of previous line
ResSpan.innerHTML="foo";
the code implemented in a void method, so the method will wait until `AddProductAsync' is being finished.
I wonder if let me know is it correct understanding of `async methods'?
Async methods are asynchronous - this means that they do not block the main execution thread and will occur in parallel at some point. If you need to wait for an async call to finish you need to either await the response (if using async/await), call Wait() (if using a Task<T>) to wait for it to finish or access the Result property (which also implicitly calls Wait).
Jon Skeet has a fantastic EduAsync series that will take you through async from nuts to bolts.
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().
I am really curious how async/await enables your program not to be halted.
I really like the way how Stephen Cleary explains async/await: "I like to think of "await" as an "asynchronous wait". That is to say, the async method pauses until the awaitable is complete(so it waits), but the actual thread is not blocked (so it's asynchornous)."
I've read that async method works synchronously till compilator meets await keywords. Well. If compilator cannot figure out awaitable, then compilator queues the awaitable and yield control to the method that called method AccessTheWebAsync. OK.
Inside the caller (the event handler in this example), the processing pattern continues. The caller might do other work that doesn't depend on the result from AccessTheWebAsync before awaiting that result, or the caller might await immediately. The event handler is waiting for AccessTheWebAsync, and AccessTheWebAsync is waiting for GetStringAsync. Let's see an msdn example:
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
// The await operator suspends AccessTheWebAsync.
// - AccessTheWebAsync can't continue until getStringTask is complete.
// - Meanwhile, control returns to the caller of AccessTheWebAsync.
// - Control resumes here when getStringTask is complete.
// - The await operator then retrieves the string result from getStringTask.
string urlContents = await getStringTask;
// The return statement specifies an integer result.
// Any methods that are awaiting AccessTheWebAsync retrieve the length value.
return urlContents.Length;
}
Another article from msdn blog says that async/await does not create new thread or use other threads from thread pool. OK.
My questions:
Where does async/await execute awaitable code(in our example downloading a web site) cause control yields to the next row of code of our program and program just asks result of Task<string> getStringTask? We know that no new threads, no thread pool are not used.
Am I right in my silly assumption that CLR just switches the current executable code and awaitable part of the method between each other in scope of one thread? But changing the order of addends does not change the sum and UI might be blocked for some unnoticeable time.
Where does async/await execute awaitable code(in our example downloading a web site) cause control yields to the next row of code of our program and program just asks result of Task getStringTask? We know that no new threads, no thread pool are not used.
If the operation is truly asynchronous, then there's no code to "execute". You can think of it as all being handled via callbacks; the HTTP request is sent (synchronously) and then the HttpClient registers a callback that will complete the Task<string>. When the download completes, the callback is invoked, completing the task. It's a bit more complex than this, but that's the general idea.
I have a blog post that goes into more detail on how asynchronous operations can be threadless.
Am I right in my silly assumption that CLR just switches the current executable code and awaitable part of the method between each other in scope of one thread?
That's a partially true mental model, but it's incomplete. For one thing, when an async method resumes, its (former) call stack is not resumed along with it. So async/await are very different than fibers or co-routines, even though they can be used to accomplish similar things.
Instead of thinking of await as "switch to other code", think of it as "return an incomplete task". If the calling method also calls await, then it also returns an incomplete task, etc. Eventually, you'll either return an incomplete task to a framework (e.g., ASP.NET MVC/WebAPI/SignalR, or a unit test runner); or you'll have an async void method (e.g., UI event handler).
While the operation is in progress, you end up with a "stack" of task objects. Not a real stack, just a dependency tree. Each async method is represented by a task instance, and they're all waiting for that asynchronous operation to complete.
Where is continuation of awaitable part of method performed?
When awaiting a task, await will - by default - resume its async method on a captured context. This context is SynchronizationContext.Current unless it is null, in which case it is TaskScheduler.Current. In practice, this means that an async method running on a UI thread will resume on that UI thread; an async method handling an ASP.NET request will resume handling that same ASP.NET request (possibly on a different thread); and in most other cases the async method will resume on a thread pool thread.
In the example code for your question, GetStringAsync will return an incomplete task. When the download completes, that task will complete. So, when AccessTheWebAsync calls await on that download task, (assuming the download hasn't already finished) it will capture its current context and then return an incomplete task from AccessTheWebAsync.
When the download task completes, the continuation of AccessTheWebAsync will be scheduled to that context (UI thread, ASP.NET request, thread pool, ...), and it will extract the Length of the result while executing in that context. When the AccessTheWebAsync method returns, it sets the result of the task previously returned from AccessTheWebAsync. This in turn will resume the next method, etc.
In general the continuation (the part of your method after await) can run anywhere. In practice it tends to run on the UI thread (e.g. in a Windows application) or on the thread pool (e.g. in an ASP .NET server). It can also run synchronously on the caller thread in some cases ... really it depends on what kind of API you're calling and what synchronization context is being used.
The blog article you linked does not say that continuations are not run on thread pool threads, it merely says that marking a method as async does not magically cause invocations of the method to run on a separate thread or on the thread pool.
That is, they're just trying to tell you that if you have a method void Foo() { Console.WriteLine(); }, changing that to async Task Foo() { Console.WriteLine(); } doesn't suddenly cause an invocation of Foo(); to behave any differently at all β it'll still be executed synchronously.
If by "awaitable code" you mean the actual asynchronous operation, then you need to realize that it "executes" outside of the CPU so there's no thread needed and no code to run.
For example when you download a web page, most of the operation happens when your server sends and receives data from the web server. There's no code to execute while this happens. That's the reason you can "take over" the thread and do other stuff (other CPU operations) before awaiting the Task to get the actual result.
So to your questions:
It "executes" outside of the CPU (so it's not really executed). That could mean the network driver, a remote server, etc. (mostly I/O).
No. Truly asynchronous operations don't need to be executed by the CLR. They are only started and completed in the future.
A simple example is Task.Delay which creates a task that completes after an interval:
var delay = Task.Delay(TimeSpan.FromSeconds(30));
// do stuff
await delay;
Task.Delay internally creates and sets a System.Threading.Timer that will execute a callback after the interval and complete the task. System.Threading.Timer doesn't need a thread, it uses the system clock. So you have "awaitable code" that "executes" for 30 seconds but nothing actually happens in that time. The operation started and will complete 30 seconds in the future.
I call this getJson() function from an async action in my controller.
I have a list of large files that each take a few seconds for ReadToEndAsync() to process.
The ReadToEndAsync() is blocking even though I'm awaiting it.
How can I call ReadToEndAsync() asynchronously?
public static async Task<T> getJson<T>(String url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(server + url);
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
String jsonString;
//get the json string from the response
using (var xx = response.GetResponseStream())
{
StreamReader reader = new StreamReader(xx, Encoding.UTF8);
jsonString = await reader.ReadToEndAsync()
}
}
Controller:
_model.list.Add(await DataRetriever.getJson<ReviewModel>(url));
_model.list.Add(await DataRetriever.getJson<ReviewModel>(url));
_model.list.Add(await DataRetriever.getJson<ReviewModel>(url));
As noted in the comments, while the method ReadToEndAsync() does not block per se β in the usual sense of the word "block": that is, the thread that calls that method continues to run β it certainly will prevent the code after the await from executing until the method has completed. Which is exactly what you want: you don't want that code to execute until the read has completed, otherwise it wouldn't have the result to operate on.
You should probably (re?)read the documentation on async and await, but briefly: the keyword async is applied to a method to signal to the compiler that it will use await. The await is used to indicate to the compiler a point in the method where the compiler should save the current execution state of the method and return.
If and when the operation to which the await keyword has been applied completes, the framework will automatically continue execution of the method where it left off. Where the method is called in a thread that is tied to a synchronization context (e.g. a GUI thread in a Winforms or WPF program), by default this "continuation" is executed in that original thread (but this can be disabled when appropriate).
Please note above that the async method returns from await statements. Thus, the method itself does not block the thread, even as the operation represented by the method does "block" in some sense of the word.
So, with that all said, it seems to me that you may be trying to get your three operations to all complete asynchronously and concurrently. If you want to do that, you need to start all of the asynchronous operations at once, rather than waiting for each to complete before proceeding to the next as you do now (i.e. via the await statement applied to the call to the getJason<T>() method).
That would look something like this:
Task<ReviewModel> task1 = DataRetriever.getJson<ReviewModel>(url1),
task2 = DataRetriever.getJson<ReviewModel>(url2),
task3 = DataRetriever.getJson<ReviewModel>(url3);
_model.list.Add(await task1);
_model.list.Add(await task2);
_model.list.Add(await task3);
(Note: in your original code example, you only used a single url value. Since I assume you don't really want to just execute the same query three different times, I went ahead and changed the code example so that each task uses a different value).
In the above, even if the second and/or third task completes before the first, the results will be added to the result list in order. But the tasks themselves are started all at the same time so that they can run concurrently.
I hope that the above not only clarifies for you whether or not the call to the method ReadToEndAsync() is blocking (it does not, though because of the way the debugger presents the execution of your code, it might seem that it does), but also provides you with the solution to the larger problem that led you to debug the method and think that it's blocking. I.e. that your JSON queries didn't execute concurrently.
If between the comments on your question, and the above answer, you still have a problem, please edit your question so that it's more clear about what exactly you are asking.
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 am writing a simple metro app. However, the API blocks when accessing files. By blocking, I mean the programs waits forever. Creating/opening a file or folder should take at most a few seconds. In this case, it takes forever.
When I run the program, it never comes back from OnTest. Is it what you get.
I understand .Wait will wait for the creation of files and folders to finishe. Maybe that's not great design. However, that's not the point.
My question is:
Do you get the same behavior (blocks the program forever)
Is it what's supposed to happen or is it a bug in WinRT? (I am using the consumer preview)
If that's the expected behavior, why does it take forever?
Here is the XAML code:
<Button Click="OnTest">Test</Button>
Here is the C# code:
private async void OnTest(object sender, RoutedEventArgs e)
{
var t = new Cache("test1");
t = new Cache("test2");
t = new Cache("test3");
}
class Cache
{
public Cache(string name)
{
TestRetrieve(name).Wait();
}
public static async Task TestRetrieve(string name)
{
StorageFolder rootFolder = ApplicationData.Current.LocalFolder;
var _folder = await rootFolder.CreateFolderAsync(name, CreationCollisionOption.OpenIfExists);
var file = await _folder.CreateFileAsync("test.xml", CreationCollisionOption.OpenIfExists);
}
}
It blocks on the second call to new Cache("test2");
I have not attempted to run your program or reproduce your problem, but I can make an educated guess as to what is going on.
Suppose you wrote yourself the following to-do list:
Put a letter to mom in the mailbox.
Set the alarm to wake me up as soon as I've read her reply.
Go to sleep.
Check the mailbox for the reply.
Read the reply.
Now do everything on that list strictly in order from top to bottom. What happens?
The problem is not with the post office or with mom; they are picking up the letter you put in the mailbox, sending it to mom, mom is writing her reply and the post office is bringing it back to you. The problem is that you never get to the fourth step because you only can start the fourth step after you complete the fifth step and the alarm wakes you up. You'll sleep forever because you are essentially waiting for your future self to wake your present self up.
Eric, Thank you for the explanation.
You're welcome.
However, I am still confused as to why my code does not work.
OK, let's break it down. What does your program really do? Let's simplify:
void M()
{
Task tx = GetATask();
tx.Wait();
}
async Task GetATask()
{
Task ty = DoFileSystemThingAsync();
await ty;
DoSomethingElse();
}
First off: what is a task? A task is an object that represents (1) a job to be done, and (2) a delegate to the continuation of the task: the thing that needs to happen after the task is done.
So you call GetATask. What does it do? Well, the first thing it does is it makes a Task and stores it in ty. That task represents the job "start some operation on the disk, and notify the I/O completion thread when it is done".
What is the continuation of that task? What has to happen after that task is done? DoSomethingElse needs to be called. So the compiler transforms the await into a bunch of code that tells the task to ensure that DoSomethingElse is called when the task is done.
The moment that the continuation of the I/O task has been set, the method GetATask returns a task to the caller. What task is that? This is a different task than the task that got stored into ty. The task that is returned is the task that represents the job do everything that the method GetATask needs to do.
What is the continuation of that task? We don't know! That is up to the caller of GetATask to decide.
OK, so let's review. We have two task objects. One represents the task "go do this thing on the file system". It will be done when the file system does its work. It's continuation is "call DoSomething". We have a second task object that represents the job "do everything in the body of GetATask". It will be done after the call to DoSomethingElse returns.
Again: the first task will be complete when the file I/O succeeds. When that happens, the file I/O completion thread will send a message to the main thread saying "hey, that file I/O you were waiting for is done. I am telling you this because it is now time for you to call DoSomethingElse".
But the main thread is not examining its message queue. Why not? Because you told it to synchronously wait until everything in GetATask, including DoSomethingElse, is complete. But the message that is telling you to run DoSomethingElse now cannot be processed because you are waiting for DoSomethingElse to be complete.
Now is it clear? You are telling your thread to wait until your thread is done running DoSomethingElse before you check to see if "please call DoSomethingElse" is in the queue of work to be performed on this thread! You are waiting until you have read the letter from mom, but the fact that you are waiting synchronously means that you are not checking your mailbox to see if the letter has arrived.
Calling Wait is obviously wrong in this case because you are waiting for yourself to do something in the future, and that's not going to work. But more generally, calling Wait completely negates the entire point of being async in the first place. Just don't do that; it doesn't make any sense to say both "I want to be asynchronous" and "but I want to synchronously wait". Those are opposites.
You're using Wait() in the constructor of the Cache class. That's going to block until whatever is currently executing asynchronously has finished.
This is not the way to design this. Constructors and async do not make sense. Perhaps a factory method approach like this would work better:
public class Cache
{
private string cacheName;
private Cache(string cacheName)
{
this.cacheName = cacheName;
}
public static async Cache GetCacheAsync(string cacheName)
{
Cache cache = new Cache(cacheName);
await cache.Initialize();
return cache;
}
private async void Initialize()
{
StorageFolder rootFolder = ApplicationData.Current.LocalFolder;
var _folder = await rootFolder.CreateFolderAsync(this.cacheName, CreationCollisionOption.OpenIfExists);
var file = await _folder.CreateFileAsync("test.xml", CreationCollisionOption.OpenIfExists);
}
}
And then you use it like this:
await Task.WhenAll(Cache.GetCacheAsync("cache1"), Cache.GetCacheAsync("cache2"), Cache.GetCacheAsync("cache3"));
TestRetrieve(name).Wait();
You're telling it to block specifically by using the .Wait() call.
Remove the .Wait() and it shouldn't block anymore.
The existing answers provide very thorough explanations of why it blocks and code examples of how to make it not block, but these many be 'more information' than some users understand. Here is a simpler 'mechanics oriented' explanation..
The way the async/await pattern works, each time you await an async method, you are "attaching" that method's async context to the current method's async context. Imagine await as passing in a magic hidden paramater "context". This context-paramater is what allows nested await calls to attach to the existing async context. (this is just an analogy...the details are more complicated than this)
If you are inside an async method, and you call a method synchronously, that synchronous method doesn't get that magic hidden async context paramater, so it can't attach anything to it. It's then an invalid operation to create a new async context inside that method using 'wait', because the new context does not get attached to your thread's existing top-level async context (because you don't have it!).
Described in terms of the code-example, the TestRetrieve(name).Wait(); is not doing what you think it's doing. It's actually telling the current thread to re-enter the async-activity-wait-loop at the top. In this example, this is the UI-thread, which is called your OnTest handler. The following picture may help:
UI-thread context looks like this...
UI-Thread ->
OnTest
Since you didn't have a connected chain of await/async calls all the way down, you never "attached' the TestRetrieve async context to the above UI-Thread async chain. Effectively, that new context you made is just dangling off in nowhere land. So when you "Wait" the UIThread, it just goes right back to the top.
For async to work, you need to keep a connected async/await chain from the top-level synchronous thread (in this case it's the UI-thread doing this) through all async actions you need to do. You can't make a constructor async, so you can't chain an async context into a constructor. You need to construct the object synchronously and then await TestRetrieve from outside. Remove the 'Wait' line from your constructor and do this...
await (new Cache("test1")).TestRetrieve("test1");
When you do this, the 'TestRetrieve' async context is properly attached, so the chain looks like this:
UI-Thread ->
OnTest ->
TestRetrieve
Now the UI-thread async-loop-handler can properly resume TestRetrieve during async completions and your code will work as expected.
If you want to make an 'async constructor', you need to do something like Drew's GetCacheAsync pattern, where you make a static Async method which constructs the object synchronously and then awaits the async method. This creates the proper async chain by awaiting and 'attaching' the context all the way down.