EDIT: Updating LongTask() to be await Task.Delay(2000); makes it work how I need, so thanks for the answers, y'all!
I am trying to call an async function from within a sync function to let the sync function keep going before the async function is finished. I don't know why the code below waits for LongTask() to complete before continuing. I thought it should only do that if I did await LongTask(). Can someone help me understand what I'm missing?
C# fiddle here
using System;
using System.Diagnostics;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
var timer = new Stopwatch();
timer.Start();
LongTask();
timer.Stop();
long ms = timer.ElapsedMilliseconds;
Console.WriteLine(ms.ToString());
}
async static void LongTask()
{
Task.Delay(2000).Wait();
}
}
Here's the short short intro to async/await
You know when you're playing some God type game where you e.g. set your settlers building a load of buildings, or cutting trees/making food etc and then you have literally nothing else to do except sit and watch them finish, then you can start again, getting the buildings to churn out knights or catapults or whatever?
It's a bit of a waste of life, you sitting there doing nothing other than waiting for something to finish, then you can carry on with some other task..
As a human you probably don't do that; you go make a cup of coffee, call a friend, hit the punchbag, maybe even go play the space exploration game, set the autopilot of whatever ship to guide you to some star system on a journey that'll take 5 mintues of waiting and watching stars pass.. Autopilot set, coffee made, buildings still not finished, bored of the punchbag.. So you go clean up..
This isn't doing things in parallel; you aren't wiping the floor with a cloth while stirring the coffe and chatting on the phone, but it's making great use of your time, cracking through the todo list by pouring a load of energy into one thing, getting as far as you can, then switching to the next thing. You do one thing at once, but when you get stuck you move onto another thing. If you sat and waited for everything you'd need 10 copies of you to get 10 stop/start jobs done
async/await is the same thing. It takes syncronous code - something that is done from start to finish in one long operation that is the sole focus of your thread's attention, even if there's a 5 minute Wait() in the middle of it where it literally sits and does nothing for 5 minutes - and chops it up into a bunch of separate methods that are controlled by a process that allows the thread to pick up where it left off of
Marking a method async is the indicator to C# that the compiler is allowed to invisbly cut the method up into pieces that can be put down and picked up when needed
await is the indicator where you're saying "I've reached a point where I need some operation to finish before I can progress any further with this; go and find something else to do". When it encounters an await your thread will stop work on your code because it's being told it to do nothing more until the background operation completes (it's not important what is doing the work, lets imagine it's some background thread) and your thread will go and do something else until the result is ready. This really simplifies a lot of programming related stuff because you only ever deal with one thread - it's code that behaves like syncronous code but goes and does something else instead of doing nothing when it gets stuck
As a keyword await has to be followed by something that is awaitable, usually a Task or Task<T> - it represents the operation that is already set to happen. When the operation is finished and the thread returns await also helpfully unwraps the Task object that was controlling this process, and gives you the result..
If you take nothing else away from this, at the very least learn:
you must mark a method as async if you want to use await inside it. You should generally make the return type of an sync method as either Task (if it returns no value) or Task<X> (if it returns a value of type X). You should also call the method a name ending in ..Async
When you start some operation that works asyncronously (you call some method that is called ..Async), and you get a Task<X> object in return, use await on it to get the X you actually want
Making an async method means the method that calls it also has to be async, and the method that calls that also has to be async.. and.. All the way up the tree and out of your code. That's how your thread can "escape" when it has to go find something else to do - it needs to escape out of your code, so you make a route for that to happen by declaring "async all the way up"
I said in the comments not to use a console app. Let's imagine you have a Windows Forms app. Win Forms apps typically have one thread that does everything. One thread draws the UI, and when you click a button it comes and runs all the code you put in the button_Click() handler. While it's doing that it's not doing its normal job of drawing the UI. You can set statusLabel.Text = "Downloading data.." as the very first line of the method, and you can launch a download of a 1 gig file, and then you can set the status Label to "Finished " + downloadedFile.Length. You click the button, and you see nothing - the UI of your app jams frozen for 30 seconds while the file downloads. Then it suddenly says "Finished 1024000000" in the label:
void button_Click(object sender, EventArgs e){
statusLabel.Text = "Starting download";
string downloadedFile = new SomeHttpDownloadStringThing("http://..");
statusLabel.Text = "Finished " + downloadedFile.Length;
}
Why? Well.. the thread that draws the UI and would have painted the label pixels on the screen got really busy downloading the file. It went into that SomeHttpDownloadStringThing method and didn't come out for 30 seconds, then it came out, set the status label text again, then it left your code and went back to whatever land it normally lives in. It drew the pixels on screen "Finished..". It never even knew it had to draw "Starting download".. That data was overwritten well before it picked up its paintbrush again
Let's turn it async:
async void button_Click(object sender, EventArgs e){
statusLabel.Text = "Starting download";
string downloadedFile = await SomeHttpDownloadStringThingAsync("http://..");
statusLabel.Text = "Finished " + downloadedFile.Length;
}
SomeHttpDownloadStringThing returned a string. SomeHttpDownloadStringThingAsync returned a Task<string>. When the UI thread hits that await imagine it tells some background thread to go download the file, puts this method on pause, and returns out of it and goes back to drawing the UI. It paints the label as "Starting ..." so you see it, and then maybe finds some other stuff to do. If you had a Timer ticking up counting how long the download had been then your timer would increment nicely too - bcause the UI thread is free to do it, it's not sitting awaiting for Windows to do the download while it does nothing other than wait.
When the download finishes, the thread is called back to where it was and it picks up from there. It doesn't run the first code again, it doesn't set the status label to "Starting" again.
It literally starts from the SomeHttpDownloadStringThingAsync part as if it had never left, the await converts the Task<string> into a string of the downlaoded file, and then the UI thread can set the "Finished.." text
The whole thing is just like the syncronous version, except that little bit in the middle where the UI thread was allowed to go back to its regular job of drawing pixels on the screen and handling other user interaction
This is why I say console apps are hard work for understanding async/await because their UI doesn't obviously do anything else while an await is in progress, unless you've arranged for something to happen, but that's more work. UI apps automatically have other stuff going on, and if you jam up the threads that do that stuff, they freeze, and turn "Not responding"
If you have an eagle eye, you'll have spotted async void on the handler even though I said "if you have a void method, make it return Task when you make it async" - winforms event handlers are a bit of a special case in that regard, you cannot make them async Task but they're an exception rather than a rule. For now, rule of thumb - avoid async void
As already mentioned in the comments:
you have to use await Task.Delay(2000) to tell the compiler that you want run Task.Delay(2000) asynchronous.
If you take a closer look in the example provided by you the compiler shows a warning:
This async methods lacks 'await'operators and will run synchronously [...]
This will hopefully demonstrate it better:
static async Task Main(string[] args)
{
var timer = Stopwatch.StartNew();
var t1 = LongTask();
var t2 = LongTask();
Console.WriteLine("Started both tasks in {0}", timer.Elapsed);
await Task.WhenAll(t1, t2);
timer.Stop();
Console.WriteLine("Tasks finished in {0}", timer.Elapsed);
}
async static Task LongTask()
{
await Task.Delay(2000);
}
Notice the change in return types of functions. Notice the output, too. Both task are waiting for something (in this case delay to expire) in parallel and at the same time, the Main function is able to continue running, printing text and then waiting for the outcome of those functions.
It is important to understand that the execution of an async function runs synchronously until it hits the await operator. If you don't have any await in an async function it will not run asynchronously (and compiler should warn about it). This is applied recursively (if you have several nested awaits) until you hit something that is actually going to be waited for. See example:
static async Task Main(string[] args)
{
var timer = Stopwatch.StartNew();
var t1 = LongTask(1);
Console.WriteLine("t1 started in {0}", timer.Elapsed);
var t2 = LongTask(2);
Console.WriteLine("Started both tasks in {0}", timer.Elapsed);
await Task.WhenAll(t1, t2);
timer.Stop();
Console.WriteLine("Tasks finished in {0}", timer.Elapsed);
}
async static Task LongTask(int id)
{
Console.WriteLine("[{0}] Before subtask 1", id);
await LongSubTask1();
Console.WriteLine("[{0}] Before subtask 2", id);
await LongSubTask2();
Console.WriteLine("[{0}] After subtask 1", id);
}
async static Task LongSubTask1(int id)
{
Console.WriteLine("[{0}] LongSubTask1", id);
await Task.Delay(1000);
}
async static Task LongSubTask2(int id)
{
Console.WriteLine("[{0}] LongSubTask2", id);
await Task.Delay(1000);
}
If you run it, you will see that the execution runs synchronously all the way down to Task.Delay call and only then it returns all the way back to the Main function.
In order to benefit from async/await, you have to use it all the way down to where it ends up calling some I/O (network, disk, etc.) you will need to wait for (or some other event that does not require constant polling to figure out, or artificially created like delay in that sample). If you need to do some expensive computation (that does not have anything async in it) without occupying some particular thread (say, UI thread in GUI application), you'd need to explicitly start new task with it, which at some later point you can await for to get its result.
My application is based on WPF.
Task is I need to show a custom busy indicator while something is working in the main window ( because the app UI will be freezed untill it complete the task). So what I particularly want is as below
// Code in main window
CustomBusyIndicator.ShowDialog();
//....
//..code that takes time
//....
CustomBusyIndicator.Close();
So I must implement a window which must be flexible to call anywhere in my main application to indicate busy.
Here two points should be kept in mind,
1. When i show CustomBusyIndicator, in background the main window should be running it's task
2. When i show CustomBusyIndicator, the CustomBusyIndicator should be always on top of main window, user must not be able to use the main window, if he switch to other application using Start+tab or something and again when he switch back to my application,the CustomBusyIndicator should be on top(if it is not closed).
When the task is completed I should be able call just close() method to close the CustomBusyIndicator from the main window as shown in code.
Easy to solve
public async void Button1_Click(Object sender, RoutedEventArgs e)
{
// get a task for the dialog, but do not await here its completion
var dialogTask = CustomBusyIndicator.ShowDialogAsync();
// await the completion of the lengthy operation
await SomeLengthOperationAsync();
// close the dialog
CustomBusyIndicator.Close();
// now await the completion of the dialog task
await dialogTask;
}
and the extension is
public static class WindowExtensions
{
public static async Task<bool?> ShowDialogAsync( this Window window )
{
await Task.Yield();
return window.ShowDialog();
}
}
If you don't know how to work with async await, just move your long running logic in a backgroundworker. There are several options for making the backgroundworker communicate without problems with the main GUI thread.
Based on your question and your level of experience I think you are way over your head with async wait. But Rufo's solution is fine too.
Google is your friend, There is a lot of information about using the backgroundworker and about async await too. It will just take a bit longer to fully grasp the potential of async await. Async await is btw not a solution for everything. I ran into a situation today where I ran in a database with EF6 that simply says it does not support async operations. Works perfectly well with sql server but this was pervasive. Total dissapointment because now me too have to use a backgroundworker where my first idea was async await.
The idea behind async await, is that the gui thread is not blocked if you are doing a long running task. It is more like a waitpoint where it will continue if that long operation is finished.
Other options are to use RX, but that difficulty level increases again.
Use the backgroundworker and you are fine, and your gui is never blocked. You can even cancel the work of the backgroundworker. Excellent solution for you.
I just started playing with my fresh Raspberry Pi 3 and Win10 IOT.
I tried a little project but encountered some problems with async/await statements.
I am not new to C#, nor with await/async, but it is my first time with UWP so I may miss some tricks for this platform compairing to the WinForms/WPF environment.
(FYI, I haven't access to a Win10 developpement machine for the moment, so below snippets may not compile right away)
Here is the standard template for a headless application on the Rpi :
public async void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.GetDeferral();
await DoSomethingAsync();
// Other irrevelant stuff then...
defferal.Complete();
}
And then an async method :
private async Task DoSomethingAsync()
{
// Something done async
await Task.Delay(1000);
} // <--- Hangs here
When deploying the app to the Pi, it enters the DoSomethingAsync method and execute its content without problem.
My issue is that the app hangs at the exiting semicolon.
Do we need to use the CoreDispatcher, the ThreadPool, or a simple new TaskFactory().StartNew(async () => { await DoSomethingAsync(); }); ?
What I don't understand is the use of the await/async should execute my method on an other thread, but it hangs the same way as if it was waiting for UI to process messages queue (WinForms/WPF background here :) )
Thank you in advance.
EDIT : This snippet works if I remove all the async stuff to make it synchronously running.
I don't see Complete() method on defferal in your code, try this:
public async void Run(IBackgroundTaskInstance taskInstance)
{
BackgroudTaskDefferal defferal = taskInstance.GetDeferral();
await DoSomethingAsync();
// Other irrevelant stuff then...
defferal.Complete();
}
That could be problem with hanging, application's waiting for signal that async operations are completed.
If you remove all the breakpoints, add debugging logs like
`System.Diagnostics.Debug.WriteLine`
The debug message would show everything is working all fine.
The hang only happens when you do the remote debugging with VS.
I suggest you open an user voice request.
I have extensively tried to search for this matter and could not reach any conclusion. I am using Xamarin with Visual Studio to design an app for Android in C# language. The app runs an async task which reads samples from the device microphone. So far there is no control of timing for this task. The code is as follows:
button.Click += async delegate
{
//do some other stuff
await read_mic_task();
}
The read_mic_task() is an async Task in which I read the samples from the microphone. I am measuring time between one and other execution using a Stopwatch and I can see the task runs with random periods. I would like to perform this task periodically and, despite searching a lot, I got nothing. Could you please give a help?
Thanks in advance!
There are multiple possibilities if you also want to share it across platforms i would go with system threading timer. This timer can also be used in a portable class.
You can use it for example like:
private System.Threading.Timer _timer;
...
// setup timer with callback
_timer = new System.Threading.Timer(OnTimerTick);
// start timer: duetime = 0 when to first execute callback (0 = right now) and intervall 5s
_timer.Change(0, 5000);
...
// stop timer
_timer.Change(Timeout.Infinite, Timeout.Infinite);
...
private void OnTimerTick(object state)
{
// do the intervall stuff here
}
public MainPage()
{
Method_1();
Method_2();
Method_3();
Method_4();
Method_5();
Method_6();
}
I am writing a Windows Phone 8.1 App (WINRT XAML). How to make these methods execute at a time from constructor? What I mean to ask is about multithreading, i want these methods to get executed sidebyside and not one after another.
Does this effect loading of application? will app load fast/slow?
First off, you don't want to execute those methods in the constructor if they are long running methods. Wait until the page is loaded:
private async void Page_Loaded(object sender, RoutedEventArgs e)
{
Task m1task = Method_1();
Task m2task = Method_2();
Task m3task = Method_3();
Task all = Task.WhenAll(m1Task, m2Task, m3Task);
await all;
}
The code will load off these operations to another thread and as long as your methods are properly implemented your UI will stay responsive (so don't use wait() for instance).
This is what a sample method could look like:
private async Task Method_1() {
// Long running operation goes here
}
If you have some heavy computations to do, wrap them into Task.Run(() => { // Code });It's really essential that you're aware of the concepts of asynchronous programming. You might want to read on here:
Do you have to put Task.Run in a method to make it async?
await vs Task.Wait - Deadlock?
When correctly use Task.Run and when just async-await
But seriously, you're writing that your methods are not UI related. You might be better off running those somewhere else (e.g. in your ViewModels or even in a background task / service).
Mark the methods as Async with return type Task.
eg. public async Task method1(){}
You won't be able to fire any UI activities from them, but they'll run outside of the main thread.