So I have the following code
private async void button1_Click(object sender, EventArgs e)
{
await DoSomethingAsync();
MessageBox.Show("Test");
}
private async Task DoSomethingAsync()
{
for (int i = 0; i < 1000000000; i++)
{
int a = 5;
}; // simulate job
MessageBox.Show("DoSomethingAsync is done");
await DoSomething2Async();
}
private async Task DoSomething2Async()
{
for (int i = 0; i < 1000000000; i++)
{
int a = 5;
} // simulate job
MessageBox.Show("DoSomething2Async is done");
}
Until both MessageBoxes are shown the main thread is block (I mean the application itself is frozen). There is obviously something wrong with my code and I can't figure out what. I've never used async/await before. this is my first attempt.
EDIT:
Actually what i want to do is to start Execution of DoSomethingAsync asynchronously so that when button is clicked the MessageBox.Show("Test"); would execute even though the DoSomethingAsync is incomplete.
I think you misunderstand what async means. It doesn't mean that the method runs in another thread!!
An async method runs synchronously until the first await, then returns a Task to the caller (unless it's async void, then it returns nothing). When the task that is being awaited completes, execution resumes after the await, usually on the same thread (if it has a SynchronizationContext).
In your case, the Thread.Sleep is before the first await, so it's executed synchronously, before control is returned to the caller. But even if it was after the await, it would still block the UI thread, unless you specifically configured the the awaiter not to capture the synchronization context (using ConfigureAwait(false)).
Thread.Sleep is a blocking method. If you want an async equivalent, use await Task.Delay(3000), as suggested in Sriram Sakthivel's answer. It will return immediately, and resume after 3 seconds, without blocking the UI thread.
It's a common misconception that async is related to multithreading. It can be, but in many cases it's not. A new thread is not implicitly spawned just because the method is async; for a new thread to spawn, it has to be done explicitly at some point. If you specifically want the method to run on a different thread, use Task.Run.
You should note that methods marked with async will no longer behave async when it lacks await. You'd have got compiler warning about this.
Warning 1 This async method lacks 'await' operators and will run
synchronously. Consider using the 'await' operator to await
non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work
on a background thread.
You should give attention to those warnings.
Do it asynchronously. When I say asynchronous it is really asynchronous not synchronous job in another thread.
Use Task.Delay which is really asynchronous. Use Task.Run for some time consuming job which is CPU bound.
private async void button1_Click(object sender, EventArgs e)
{
await DoSomethingAsync();
}
private async Task DoSomethingAsync()
{
await Task.Delay(3000); // simulate job
MessageBox.Show("DoSomethingAsync is done");
await DoSomething2Async();
}
private async Task DoSomething2Async()
{
await Task.Delay(3000); // simulate job
MessageBox.Show("DoSomething2Async is done");
}
You're not doing anything asynchronously. Try:
await Task.Run(() => Thread.Sleep(3000))
When you await a method, what you are effectively doing is providing a callback, with the code that follows it as what is executed once it finishes (in previous incarnations of async you actually had to set this up yourself). If you don't await anything then the method isn't really an asynchronous one.
For further information, you could do worse than looking here:
http://msmvps.com/blogs/jon_skeet/archive/2011/05/08/eduasync-part-1-introduction.aspx
Following your edit; try this:
public void MyMessageBox()
{
var thread = new Thread(() =>
{
MessageBox.Show(...);
});
thread.Start();
}
Although, are you sure it's really a message box you want? I would have thought a status bar / progress bar update would fit better.
In the DoSomethingAsync Thread.Sleep is called before await and in DoSomething2Async no async task is done.
Related
I don't quite understand the difference between Task.Wait and await.
I have something similar to the following functions in a ASP.NET WebAPI service:
public class TestController : ApiController
{
public static async Task<string> Foo()
{
await Task.Delay(1).ConfigureAwait(false);
return "";
}
public async static Task<string> Bar()
{
return await Foo();
}
public async static Task<string> Ros()
{
return await Bar();
}
// GET api/test
public IEnumerable<string> Get()
{
Task.WaitAll(Enumerable.Range(0, 10).Select(x => Ros()).ToArray());
return new string[] { "value1", "value2" }; // This will never execute
}
}
Where Get will deadlock.
What could cause this? Why doesn't this cause a problem when I use a blocking wait rather than await Task.Delay?
Wait and await - while similar conceptually - are actually completely different.
Wait will synchronously block until the task completes. So the current thread is literally blocked waiting for the task to complete. As a general rule, you should use "async all the way down"; that is, don't block on async code. On my blog, I go into the details of how blocking in asynchronous code causes deadlock.
await will asynchronously wait until the task completes. This means the current method is "paused" (its state is captured) and the method returns an incomplete task to its caller. Later, when the await expression completes, the remainder of the method is scheduled as a continuation.
You also mentioned a "cooperative block", by which I assume you mean a task that you're Waiting on may execute on the waiting thread. There are situations where this can happen, but it's an optimization. There are many situations where it can't happen, like if the task is for another scheduler, or if it's already started or if it's a non-code task (such as in your code example: Wait cannot execute the Delay task inline because there's no code for it).
You may find my async / await intro helpful.
Based on what I read from different sources:
An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.
To wait for a single task to complete, you can call its Task.Wait method. A call to the Wait method blocks the calling thread until the single class instance has completed execution. The parameterless Wait() method is used to wait unconditionally until a task completes. The task simulates work by calling the Thread.Sleep method to sleep for two seconds.
This article is also a good read.
Some important facts were not given in other answers:
async/await is more complex at CIL level and thus costs memory and CPU time.
Any task can be canceled if the waiting time is unacceptable.
In the case of async/await we do not have a handler for such a task to cancel it or monitoring it.
Using Task is more flexible than async/await.
Any sync functionality can by wrapped by async.
public async Task<ActionResult> DoAsync(long id)
{
return await Task.Run(() => { return DoSync(id); } );
}
async/await generate many problems. We do not know if await statement will be reached without runtime and context debugging. If first await is not reached, everything is blocked. Sometimes even when await seems to be reached, still everything is blocked:
https://github.com/dotnet/runtime/issues/36063
I do not see why I must live with the code duplication for sync and async method or using hacks.
Conclusion: Creating Tasks manually and controlling them is much better. Handler to Task gives more control. We can monitor Tasks and manage them:
https://github.com/lsmolinski/MonitoredQueueBackgroundWorkItem
Sorry for my english.
Can anyone explain to me why second Working! shows after Done ?
Stating
Doing Work
Working!
Done
Working!
Work completed
Second question why can't I just do like below to get Task result:
Task result = await LongOperation();
And last question is what would be the reason to use Task.Run on behalf with await/async for instance in my code? Where could it be used or is it not good to use it?
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting");
var worker = new Worker();
worker.DoWork();
Console.WriteLine("Done");
Console.ReadKey();
}
}
public class Worker
{
public async void DoWork()
{
Console.WriteLine("Doing work");
await LongOperation();
await LongOperation();
Console.WriteLine("Work completed");
}
private async Task LongOperation()
{
Console.WriteLine("Working!");
await Task.Delay(200);
}
}
This is because you have declared DoWork() asynchronous with a return type of void. This makes it a "fire and forget" method that is running asynchronously. If you have DoWork() return a Task instead of void, you can await it, and that would ensure your "Done" message would occur after DoWork() has completed execution.
Additionally, await unwraps the task result, so you cannot await it and get the value at the same time. If you wish to use the Task result directly, do not await it.
There is no specific area in the code you specified where you should be using Task.Run().
Working shows after Done! because in your static void Main you aren't waiting for worker.DoWork(); to complete, so the program executes the next line. You should change DoWork method like this:
public async Task DoWork()
{
//
}
And change the call to it like this:
worker.DoWork().GetAwaiter().GetResult();
You can't because using await your LongOperation will not return a Task. For example if you had a signature like this, when you use await you unwrap the result:
public Task<int> GiveANumberAsync()
{
return Task.FromResult(12);
}
int result = await GiveANumberAsync();
For this question I think I can't explain better than Stephen in this answer, where he says:
Use Task.Run to call CPU-bound methods.
There reason "Done!" appears sooner than you expect is because you do not have await in front of worker.DoWork(); (and DoWork needs to return a Task to be able to use await). So what happens is DoWork() returns immediately with execution deferred to another thread, and immediately goes to next line which is the console write "done".
Regarding Task result = await LongOperation();, await takes in as parameter awaitable object (i.e. Task), examines its .Result property on your behalf, extracts the result and returns it. So you either drop await to get the task instance, or you put await to wait for task completion and extracting the actual return value of the call.
There are a few reasons to use Task.Run or through task factory, one example being passing lambda function for execution (possibly with closure). I would refer to MSDN library on TPL for detailed dive.
Taking your questions one by one:
In Main, you do not await DoWork. This means that it is invoked, and then execution of the code in the Main continues, without waiting for DoWork to finish. As such, "Done" is printed to the console right away before the second "Working".
This isn't what the await keyword does. From the documentation:
The await operator is applied to a task in an asynchronous method to suspend the execution of the method until the awaited task completes. The task represents ongoing work. [...]
The task to which the await operator is applied typically is the return value from a call to a method that implements the Task-Based Asynchronous Pattern. Examples include values of type Task or Task<TResult>.
Effectively, in order to await a method, it must have return type Task<T>, where T is the actual type of what you return in your code. Your method LongOperation doesn't actually return anything in this example.
Task.Run is used to run any method or block of code as a Task. It can be fired and forgotten (Task.Run([something];), or awaited like any other task (await Task.Run([something]);. See the documentation for it here, though I'm not sure it will be much help. User Stephen Cleary explained it well in this answer, along with some other pertinent information.
Trying to advance from using BackgroundWorker to Task, I am getting confused on how to keep the background job running without calling Wait().
This is the background job (simplified):
private async Task RunAsync()
{
HttpResponseMessage response = await TheHttpClient.GetAsync(Path);
if (response.IsSuccessStatusCode)
{
textBox_Response.Text = await response.Content.ReadAsStringAsync();
}
}
When the Send button is clicked, the above code should run, but because the background code has more than one await async calls, I guess that there are several Wait() calls needed:
private void button_Send_Click(object sender, EventArgs e)
{
Task t = RunAsync();
while (!t.IsCompleted)
{
t.Wait();
}
}
But this would block the GUI during the entire processing time of the background job.
How can I start the background job and return immediately from the button click handler, while allowing the background job to run all async calls?
I know how to achieve this with the BackgroundWorker, should I not use a Task here?
Event handlers are the only place you are allowed to do async void, what you do is make the event handler async and await it there
private async void button_Send_Click(object sender, EventArgs e)
{
await RunAsync();
//Do code here that needs to run after RunAsync has finished.
}
Quite often people think that async await is an asynchronous process performed by several threads, but in fact it is all done by one thread, unless you start a new thread using Task.Run or similar functions.
In this interview (somewhere in the middle. Search for async) Eric Lippert compared the async-await by the works of a cook in a restaurant. If he is toasting bread, he could wait for the bread to be ready before boiling the eggs, OR he could start boiling eggs and get back to the bread afterwards. It looks like the cook is doing two things at the time, but in fact he is only doing one thing, and whenever he has to wait for something he starts looking around to see if he can do other things.
If your one-and-only thread calls an asynchronous function, without awaiting for it. Your one-and-only thread starts executing that function until he sees an await. If he sees one, he doesn't wait until the async function completes, instead he remembers where he was awaiting and goes up in his call stack to see if his caller has something else to do (== is not awaiting). The caller can do the next statements until he meets an await. In that case control is given back up the call stack to the caller until he awaits etc. If your one-and-only thread is awaiting in all functions in the call stack control is given back to the first await. When that is finished your thread starts doing the statements after the await until he meets another await, or until the function is finished.
You can be certain that every async function has an await somewhere. If there is no await it is not meaningful to create it as an async function. In fact your compiler will warn you if you forgot to await somewhere in your async function.
In your example, you can expect an error, or at least a warning that you forgot to declare your button_send_click async. Without this the procedure can't await.
But after you've declared it async, and the button is pressed, your GUI-thread will call RunAsync where it will enter function TheHttpClient.GetAsync.
Inside this function is an await ReadAsStringAsync, and because ReadAsStringAsync is declared async, we can be certain that that function has an await in it. As soon as this await is met, control is given back to your TheHttpClient.GetAsync. This function would be free to perform the next statement if it didn't await. An example would be like this:
private async Task RunAsync()
{
var responseTask = TheHttpClient.GetAsync(Path);
// because no await, your thread will do the following as soon as GetAsync encounters await:
DoSomethingUseFul();
// once your procedure has nothing useful to do anymore
// or it needs the result of the responseTask it can await:
var response = await responseTask;
if (response.IsSuccessStatusCode)
...
The await is after DoSomethingUseful(). Therefore, the function can't continue. Instead of doing nothing until responseTask is finished, control is given back to the caller: button_send_click. If that function wasn't await it would be free to do other things. But since the button_send_click is awaiting control is given back to the caller: your UI is free to do other things.
But remember: it is always the one-and-only cook who makes your breakfast Your thread can do only one thing at a time
The advantage is that you won't run into difficulties you have with multiple threads. The disadvantage is that as long as your thread doesn't meet an await, it is too busy to do other things.
If you need to do some lengthy calculation while you don't want to be busy doing the calculation you can start a separate thread doing this calculation. This gives your thread time to do other things, like keeping the UI responsive until it needs the results of the calculations:
private async void Button1_Clicked(object sender, ...)
{
var taskLengthyCalculation = Task.Run( () => DoLengthyCalculation(...));
// while a different thread is doing calculations
// I am free to do other things:
var taskRunAsync = RunAsync();
// still no await, when my thread has to await in RunAsync,
// the next statement:
DoSomethingUseful();
var result = await taskRunAsync();
var resultLengthyCalculation = await taskLengthyCalculation;
I have a method like this:
async Task foo() {
foreach (DataGridViewRow row in dataGridView1.SelectedRows) {
// ...
}
}
called like this:
await Task.Run(() =>
{
foo();
});
I just noticied that code is acessing dataGridView1.SelectedRows directly, without invoke and it's working fine. Am I performing an invalid operation? Is this supposed to work or must I use invoke here?
The official answer is that is depends on who calls your foo function. Is it the main thread, or could it be a different thread?
If it is the main thread (better: the thread that created the control), than you don't need an Invoke. Async does not influence this
The following is done by the UI thread, and will work fine.
public async void Button1_Clicked(object sender, ...)
{
await Foo();
}
Quite often people think that async-await is done by several threads. But in fact it is not. A thread in an async function performs all statements until it meets an await. Instead of really waiting until the awaited function completes, it goes up in its call stack to see if it can do something else.
This is perfectly explained in Eric Lippert's restaurant metaphor (search on the page for async). Instead of waiting until the bread is toasted, the cook starts boiling eggs. But it is still the same cook.
When you see code where an async function is called without await, the thread will do the call until it meets an await and will perform the statements after the not-awaited call instead of doing nothing.
private async void Button1_clicked(object sender, ...)
{
var taskFoo = this.Foo()
// because not await: the thread will do the things in Foo until it meets
// an await. Then it returns back to do the next statements:
DoSomething();
// if this function has nothing more to do, or if it needs the result
// of Foo, await Foo:
await taskFoo;
ProcessFooResult();
}
This await for taskFoo has the effect control is given back to my caller (still the same thread), until my caller awaits. In that case control is given to his caller until await etc.
The only time a different thread is involved is when you actively start it, usually using:
var myTask = Task.Run( () => DoSomething() );
// Because there is no await, your thread will do immediately the next
// statements until an await:
DoOtherThings();
await myTask();
Now DoSomething is performed by a different thread. If you need to access UI controls you'll need InvokeRequired and Invoke.
Another helpful story about async-await: Stephen Cleary about async-await
It's because you use async and await instead of creating a new Thread / BackgroundWorker.
In my opinion it is never bad to use Invoke when interacting with Controls.
I have just tested something that I was sure would fail miserably, but to my surprise, it worked flawlessly, and proves to myself that I am still quite mystified by how async-await works.
I created a thread, passing an async void delegate as the thread's body.
Here's an oversimplification of my code:
var thread = new Thread( async () => {
while( true ) {
await SomeLengthyTask();
...
}
});
thread.Start();
thread.Join();
The thing is that as far as I understand, when the execution hits the await keyword, there is an implicit return from the method, in this case the body of the looping thread, while the rest of the code is wrapped in a callback continuation.
Because of this fact, I was pretty sure that the thread would terminate as soon as the await yielded execution, but that's not the case!
Does anybody know how this magic is actually implemented? Is the async functionality stripped down and the async waits synchronously or is there some black magic being done by the CLR that enables it to resume a thread that has yielded because of an await?
The thread is indeed terminated very quickly.
But since the Thread constructor doesn't accept an async lambda what you got there is an async void delegate.
The original thread will end and the continuation (the rest after the await) will be posted to the ThreadPool and eventually run on another thread.
You can test that by checking the thread id:
var thread = new Thread(async () =>
{
while (true)
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
await SomeLengthyTask();
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
});
thread.Start();
thread.Join();
Console.ReadLine();
Output:
3
5
5
...
5
To make the example simpler let's assume you have this Run method:
void Run(Action action)
{
action();
}
And you call it with your async delegate
Run(async () =>
{
while(true)
{
await SomeLengthyTask();
...
}
});
The execution of Run will complete almost immediately when it reaches the first await and returns. The rest of the async delegate will continue on the ThreadPool with another thread.
Generally, each time you reach an await in the execution of an async method the thread is lost and the continuation (the rest after the awaited task completes) will be posted to the ThreadPool (unless if there's a SynchronizationContext present, like in the UI thread). It may be that it execution will be on the same thread (as in my example with 5) but it also may not.
In your case the thread you create explicitly isn't part of the ThreadPool so it will definitely be terminated and the rest will run on a different thread.