Related
I'm new with C#. I'm writing window form for sorting files inside folder according to it extension.
It's work when do the task with one folder but I modified it to do it from multiple item in listbox.
private async void startBtn_Click(object sender, EventArgs e)
{
if (this.listBox1.Items.Count != 0)
{
this.statusLabel.ForeColor = Color.DodgerBlue;
this.statusLabel.Text = "Sorting";
this.startBtn.Enabled = false;
this.removeOtherCheck.Enabled = false;
this.workerCounter.Enabled = false;
foreach (var item in this.listBox1.Items)
{
if (Directory.Exists( (string)item ))
{
await Task.Run(() => startTask((string)item, this.removeOtherCheck.Checked, this.workerCounter.TabIndex));
}
}
FinishedTask();
}
private async void startTask(string path, bool removeOtherFlag, int worker)
{
await Task.Run(() => doJob(path, removeOtherFlag, worker));
}
private void FinishedTask()
{
this.statusLabel.ForeColor = Color.LimeGreen;
this.statusLabel.Text = "Finished";
this.startBtn.Enabled = true;
this.removeOtherCheck.Enabled = true;
this.workerCounter.Enabled = true;
}
//this method are seperate but I put it here so you guy can see it
public static void doJob(string directory,bool removeOtherFlag, int worker)
{
// loop in directory
createFolders(directory); // create extension folder
string[] all_files = Directory.GetFiles(directory);
Parallel.ForEach(all_files, new ParallelOptions { MaxDegreeOfParallelism = worker }, (item) => multiprocessingFiles(item));
}
if(removeOtherFlag == true) deleteOtherFolder(Path.Combine(directory,"other"));
removeEmptyFolder(directory); // remove empty extension folder
}
I'm gonna explain my task.
first I click start button when process start it will disable all buttons, then loop for each items in listbox and sorting all files in folder.
when everything finished it will show finished label and enable all buttons.
the thing is, it show finished label and re-enable all buttons before removeEmptyFolder() doing it job.
I try change Parallel.forEach to Parallel.For but it's not doing my thing.
EDIT
Thank you for all answer.
Thank Harald Coppoolse for your conclusion.
Paulo Morgado is right.
I remove startTask and change
await Task.Run(() => startTask((string)item, this.removeOtherCheck.Checked, this.workerCounter.TabIndex));
to
await Task.Run(() => doJob(item, this.removeOtherCheck.Checked, this.workerCounter.TabIndex));
Now everything is working perfectly as I want.
Thank you everyone.
Are you looking for someting like Task.WaitAll(params Task[] tasks)?
Then you could cange doJob to async by,
replaceing Parallel.ForEach with:
var tasks = all_files.Select(f => Task.Run(multiprocessingFiles(f)));
await Task.WaitAll(tasks);
Or if you want to limit the max parallel tasks:
Create non running tasks via Task t = new Task(() => doSometing());
and start them in batches with t.Start(); and await Task.WaitAll(batch);
However as pointed out in the comments I do not think this will improve performace.
In winforms, when you use async-await, you only use Task.Run when you need to start an extra thread that will do a job that takes some considerable amount of time, longer than you want your program to freeze. You don't call Task.Run for async methods, because properly designed async methods won't freeze your UI.
As soon as a thread that executes an async method sees await, it doesn't wait idly for the procedure until it is finished, instead if goes up its call stack to execute code until is sees an await. Goes up the call stack again, and executes code until is sees an await, etc.
Result: if an async event handler only uses async methods, your UI won't freeze. Unless one of the async methods does some heavy calculations (= use long non-async functionality)
If you want to keep your UI responsive during those heavy calculations, you should create an async method that calls the procedure with the heavy calculations using Task.Run.
But I did all that!
Yes you did, but you also had an async function that called another async fucntion using Task.Run! And that was not necessarry.
BTW, it might be a good idea to stick to coding conventions, like using camel casing and adding Async in async methods. This will help future readers to understand your code.
void DoJob(...){...} // your time consuming method with heavy calculations
The async version of DoJob. Apparently there is nothing we can do async in DoJob, so this version has to call the DoJob:
async Task DoJobAsync(...)
{
// call the non-async version on a separate thread:
await Task.Run( () => DoJob(...)).ConfigureAwait(false);
}
I named the procedure DoJobAsync, because the pre- and postconditions are the same as in DoJob. This matches all other non-async / async pairs: Stream.Write and Stream.WriteAsync, File.Read and File.ReadAsync, Queryable.ToList and Queryable.ToListAsync.
If in future versions DoJobAsync can use some async methods, for instance because someone invents a procedure MultiprocessingFilesAsync, then only DoJobAsync has to change, no one else will know.
For ConfigureAwait(false) see Stephen Cleary's [Best Practices in Asynchronous Programming][1]
BTW: are you sure that it is wise to do the disk handling in a Parallel.Foreach? Did you measure that it is more efficient than a standard foreach?
Anyway, apparently you have some user interface element that will start the process of "doing the job" While this job is being processed, you want to give some visual information to the operator that the job is busy, and you want to tell the operator that the job is finished. You already invented FinishedTask, why not create a StartTask (and use better descriptive names: verbs for methods)
void ShowTaskStarted() {...}
void ShowTaskCompleted() {...} // was: FinishedTask
Apparently the items in listBox1 are strings.
async Task ProcessItems(IEnumerable<string> itemsToProcess,
bool removeOtherFlag, int worker) // TODO: invent proper name
{
foreach (string itemToProcess in itemsToProcess)
{
await DoJobAsync(itemToProcess, removeOtherFlag, worker);
}
}
If you think that you can start a second DoJobAsync before the first has completely finished, then start the next job before the previous one is completed:
List<Task> jobs = new List<Task>();
foreach (string itemToProcess in itemsToProcess)
{
Task jobTask = DoJobAsync(itemToProcess, removeOtherFlag, worker);
jobs.Add(jobTask);
}
await Task.WhenAll(jobs);
Because you job is some disk handling, I'm not sure it is wise to do this, but keep this in mind, if for instance you are starting tasks which can be startedwhile the previous one is not finished.
Until now, the procedures didn't know that the data came from a listbox, nor from a CheckBox or a TabControl. I did this, because if later you decide to change the source of the data, for instance a ComboBox, or a DataGridView, these procedures don't have to change. Below is the first procedure that knows about your form.
This is a strict separation of your Model (= data and how the data is processed) and the View (= how the data is displayed).
Other advantages of separating your Model from your View:
you can put the Model outside you Form (the Form HAS the Model = aggregation, or composition). This way, this Model can be used by several Forms.
a separated Model can be unit tested without the Form
If you give the Model an interface, you can change the Model, without having to change the Form.
With the interface, you can mock the model during development of your interface.
So consider to always separate your Model from your View.
The View
I don't know what is in your listbox, so I can't give the next procedure a proper name.
async Task ProcessListBox() // TODO: proper name
{
ShowTaskStarted();
var itemsToProcess = this.ListBox1.Items.ToList();
var removeOtherCheck = this.removeOtherCheck.Checked;
var worker = this.workerCounter.TabIndex;
await ProcessItems(itemsToProcess, removeOtherCheck, worker);
ShowTaskCompleted();
}
And finally: you want to process the ListBox when the operator clicks the start button:
async void StartButton_Clicked(object sender, ...)
{
await ProcessLisbBox().ConfigureAwait(false);
}
Because I separated the action (what must be done) from the trigger (when must it be done), the following will be a one liner method:
async void MenuItem_EditStart_Clicked(object sender, ...)
{
await ProcessLisbBox().ConfigureAwait(false);
}
Or maybe you want to do it during loading the form: add one line is enough
Conclusions
When using async-await: go async all the way.
async methods always call async versions of other methods
If a time consuming method doesn't have an async alternative, create one, and let it Task.Run the non-async version. Outside this procedure no one knows that a separate thread is started.
conventions: async methods are suffixed Async
Don't make one procedure that does everything. Smaller procedures are easier to understand, easier to reuse, easier to change and to unit test
Separate the model from the view, preferably using an interface
CamelCase your Methods, use Verbs.
[1]: https://learn.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming
I have to call my API and show waiting PictureBox(wait.gif) until API get complete and return the data to bind my custom control into tablepanellayout.
I can't use BackgroundWorker class here because it has cross-thread issue with my sub control in custom control.
Here I have only idea to do that, is call child thread from main thread but until its get executed completely show the PictureBox(wait.gif) and block the rest code to be executed.
Can anybody suggest me how to do it exactly or please provide some code snippet for example.
There are two articles that helped me a lot understanding async-await:
This interview with Eric Lippert. Search somewhere in the middle for async aawait. Eric compares async await with a cook who doesn't wait for the water to boil, but instead looks around if he can do something else in the mean time.
Async Await by the ever so helpful Stephen Cleary
For WinForms you do the following:
If your data query function has async versions to fetch the data, use that function. Think of functions like SqlConnection.OpenAsync, Dapper.QueryAsync etc
If your data querier has no async versions make it async using Task.Run
Every function that calls async functions should be declared async itself
Every async function returns Task instead of void and Task<TResult> instead of TResult.
The only exception is the event handler: this function returns void instead of Task
the calls to other async functions should be awaited before your async returns.
.
// The event handler: make async. The only one that still returns void
async void OnButton1_clicked(object sender, ...)
{
// start fetching the data. Don't await yet, you'll have other things to do
Task<MyData> fetchDataTask = FetchData(...);
// meanwhile: show the user that you are busy:
this.ShowBusy(true); // show picture box?
// if needed do other things you can do before the data is fetched
this.ClearTable();
// once you have nothing meaningful to do, await for your data
MyData fetchedData = await fetchDataTask;
this.ProcessData(fetchedData);
// finished:
this.ShowBusy(false); // remove picture box
}
Async version of the function that fetched the data:
async Task<IQueryable<MyData>> FetchDataAsync(myParams)
{
using (SqlConnection dbConnection = new SqlConnection(...)
{
// open the connection, don't wait yet:
Task taskOpen = sqlCommand.OpenAsync();
// continue while opening:
using (var sqlCommand = new SqlCommand(...))
{
cmd.Parameters.AddWithValue(...);
// before executing the query: wait until OpenAsync finished:
await taskOpen;
// read the data. If nothing to do: await, otherwise use Task similar to Open
SqlDataReader dataReader = await cmd.ExecuteReaderAsync();
foreach (var row in dataReader)
{
... (some Await with GetFieldValueAsync
}
}
}
}
I'm not really familiar with reading SQL data on such a low level, I prefer entity framework and dapper, so there might be an error in my SqlReader stuff. Maybe someone can correct this. Still you'll get the gist.
If you write it like this, your program will be pretty responsive: Whenever the procedure has to await for something, control is given back to the caller of the function who can continue processing until he meets an await, when control is given back to the caller, who continues processing, etc.
Note that this won't help you if your program is not waiting for something. If your main thread does some heavy calculations for several seconds, your program won't be responsive. Consider creating an async function that will do this for your using Task.Run
If you have programmed like this, all threads performing your functions will have the same context: it will be as if only the UI-thread is involved. No need for mutexes, semaphores, InvokeRequired etc.
I am trying to understand concurrency by doing it in code. I have a code snippet which I thought was running asynchronously. But when I put the debug writeline statements in, I found that it is running synchronously. Can someone explain what I need to do differently to push ComputeBB() onto another thread using Task.Something?
Clarification I want this code to run ComputeBB in some other thread so that the main thread will keep on running without blocking.
Here is the code:
{
// part of the calling method
Debug.WriteLine("About to call ComputeBB");
returnDTM.myBoundingBox = await Task.Run(() => returnDTM.ComputeBB());
Debug.WriteLine("Just called await ComputBB.");
return returnDTM;
}
private ptsBoundingBox2d ComputeBB()
{
Debug.WriteLine("Starting ComputeBB.");
Stopwatch sw = new Stopwatch(); sw.Start();
var point1 = this.allPoints.FirstOrDefault().Value;
var returnBB = new ptsBoundingBox2d(
point1.x, point1.y, point1.z, point1.x, point1.y, point1.z);
Parallel.ForEach(this.allPoints,
p => returnBB.expandByPoint(p.Value.x, p.Value.y, p.Value.z)
);
sw.Stop();
Debug.WriteLine(String.Format("Compute BB took {0}", sw.Elapsed));
return returnBB;
}
Here is the output in the immediate window:
About to call ComputeBB
Starting ComputeBB.
Compute BB took 00:00:00.1790574
Just called await ComputBB.
Clarification If it were really running asynchronously it would be in this order:
About to call ComputeBB
Just called await ComputBB.
Starting ComputeBB.
Compute BB took 00:00:00.1790574
But it is not.
Elaboration
The calling code has signature like so: private static async Task loadAsBinaryAsync(string fileName) At the next level up, though, I attempt to stop using async. So here is the call stack from top to bottom:
static void Main(string[] args)
{
aTinFile = ptsDTM.CreateFromExistingFile("TestSave.ptsTin");
// more stuff
}
public static ptsDTM CreateFromExistingFile(string fileName)
{
ptsDTM returnTin = new ptsDTM();
Task<ptsDTM> tsk = Task.Run(() => loadAsBinaryAsync(fileName));
returnTin = tsk.Result; // I suspect the problem is here.
return retunTin;
}
private static async Task<ptsDTM> loadAsBinaryAsync(string fileName)
{
// do a lot of processing
Debug.WriteLine("About to call ComputeBB");
returnDTM.myBoundingBox = await Task.Run(() => returnDTM.ComputeBB());
Debug.WriteLine("Just called await ComputBB.");
return returnDTM;
}
I have a code snippet which I thought was running asynchronously. But when I put the debug writeline statements in, I found that it is running synchronously.
await is used to asynchronously wait an operations completion. While doing so, it yields control back to the calling method until it's completion.
what I need to do differently to push ComputeBB() onto another thread
It is already ran on a thread pool thread. If you don't want to asynchronously wait on it in a "fire and forget" fashion, don't await the expression. Note this will have an effect on exception handling. Any exception which occurs inside the provided delegate would be captured inside the given Task, if you don't await, there is a chance they will go about unhandled.
Edit:
Lets look at this piece of code:
public static ptsDTM CreateFromExistingFile(string fileName)
{
ptsDTM returnTin = new ptsDTM();
Task<ptsDTM> tsk = Task.Run(() => loadAsBinaryAsync(fileName));
returnTin = tsk.Result; // I suspect the problem is here.
return retunTin;
}
What you're currently doing is synchronously blocking when you use tsk.Result. Also, for some reason you're calling Task.Run twice, once in each method. That is unnecessary. If you want to return your ptsDTM instance from CreateFromExistingFile, you will have to await it, there is no getting around that. "Fire and Forget" execution doesn't care about the result, at all. It simply wants to start whichever operation it needs, if it fails or succeeds is usually a non-concern. That is clearly not the case here.
You'll need to do something like this:
private PtsDtm LoadAsBinary(string fileName)
{
Debug.WriteLine("About to call ComputeBB");
returnDTM.myBoundingBox = returnDTM.ComputeBB();
Debug.WriteLine("Just called ComputeBB.");
return returnDTM;
}
And then somewhere up higher up the call stack, you don't actually need CreateFromExistingFiles, simply call:
Task.Run(() => LoadAsBinary(fileName));
When needed.
Also, please, read the C# naming conventions, which you're currently not following.
await's whole purpose is in adding the synchronicity back in asynchronous code. This allows you to easily partition the parts that are happenning synchronously and asynchronously. Your example is absurd in that it never takes any advantage whatsoever of this - if you just called the method directly instead of wrapping it in Task.Run and awaiting that, you would have had the exact same result (with less overhead).
Consider this, though:
await
Task.WhenAll
(
loadAsBinaryAsync(fileName1),
loadAsBinaryAsync(fileName2),
loadAsBinaryAsync(fileName3)
);
Again, you have the synchronicity back (await functions as the synchronization barrier), but you've actually performed three independent operations asynchronously with respect to each other.
Now, there's no reason to do something like this in your code, since you're using Parallel.ForEach at the bottom level - you're already using the CPU to the max (with unnecessary overhead, but let's ignore that for now).
So the basic usage of await is actually to handle asynchronous I/O rather than CPU work - apart from simplifying code that relies on some parts of CPU work being synchronised and some not (e.g. you have four threads of execution that simultaneously process different parts of the problem, but at some point have to be reunited to make sense of the individual parts - look at the Barrier class, for example). This includes stuff like "making sure the UI doesn't block while some CPU intensive operation happens in the background" - this makes the CPU work asynchronous with respect to the UI. But at some point, you still want to reintroduce the synchronicity, to make sure you can display the results of the work on the UI.
Consider this winforms code snippet:
async void btnDoStuff_Click(object sender, EventArgs e)
{
lblProgress.Text = "Calculating...";
var result = await DoTheUltraHardStuff();
lblProgress.Text = "Done! The result is " + result;
}
(note that the method is async void, not async Task nor async Task<T>)
What happens is that (on the GUI thread) the label is first assigned the text Calculating..., then the asynchronous DoTheUltraHardStuff method is scheduled, and then, the method returns. Immediately. This allows the GUI thread to do whatever it needs to do. However - as soon as the asynchronous task is complete and the GUI is free to handle the callback, the execution of btnDoStuff_Click will continue with the result already given (or an exception thrown, of course), back on the GUI thread, allowing you to set the label to the new text including the result of the asynchronous operation.
Asynchronicity is not an absolute property - stuff is asynchronous to some other stuff, and synchronous to some other stuff. It only makes sense with respect to some other stuff.
Hopefully, now you can go back to your original code and understand the part you've misunderstood before. The solutions are multiple, of course, but they depend a lot on how and why you're trying to do what you're trying to do. I suspect you don't actually need to use Task.Run or await at all - the Parallel.ForEach already tries to distribute the CPU work over multiple CPU cores, and the only thing you could do is to make sure other code doesn't have to wait for that work to finish - which would make a lot of sense in a GUI application, but I don't see how it would be useful in a console application with the singular purpose of calculating that single thing.
So yes, you can actually use await for fire-and-forget code - but only as part of code that doesn't prevent the code you want to continue from executing. For example, you could have code like this:
Task<string> result = SomeHardWorkAsync();
Debug.WriteLine("After calling SomeHardWorkAsync");
DoSomeOtherWorkInTheMeantime();
Debug.WriteLine("Done other work.");
Debug.WriteLine("Got result: " + (await result));
This allows SomeHardWorkAsync to execute asynchronously with respect to DoSomeOtherWorkInTheMeantime but not with respect to await result. And of course, you can use awaits in SomeHardWorkAsync without trashing the asynchronicity between SomeHardWorkAsync and DoSomeOtherWorkInTheMeantime.
The GUI example I've shown way above just takes advantage of handling the continuation as something that happens after the task completes, while ignoring the Task created in the async method (there really isn't much of a difference between using async void and async Task when you ignore the result). So for example, to fire-and-forget your method, you could use code like this:
async void Fire(string filename)
{
var result = await ProcessFileAsync(filename);
DoStuffWithResult(result);
}
Fire("MyFile");
This will cause DoStuffWithResult to execute as soon as result is ready, while the method Fire itself will return immediately after executing ProcessFileAsync (up to the first await or any explicit return someTask).
This pattern is usually frowned upon - there really isn't any reason to return void out of an async method (apart from event handlers); you could just as easily return Task (or even Task<T> depending on the scenario), and let the caller decide whether he wants his code to execute synchronously in respect to yours or not.
Again,
async Task FireAsync(string filename)
{
var result = await ProcessFileAsync(filename);
DoStuffWithResult(result);
}
Fire("MyFile");
does the same thing as using async void, except that the caller can decide what to do with the asynchronous task. Perhaps he wants to launch two of those in parallel and continue after all are done? He can just await Task.WhenAll(Fire("1"), Fire("2")). Or he just wants that stuff to happen completely asynchronously with respect to his code, so he'll just call Fire("1") and ignore the resulting Task (of course, ideally, you at the very least want to handle possible exceptions).
Ths situtation:
I get from different internet locations, json objects.
These containsmany Geocoordinates that I put onto a BingMap.
That works perfect very well.
The Problem:
but when I fetch the data from the internet locations I get a blocking ui.
Is there a method to run that in background?
I tried the async functionality but I get there a blocking UI too..
Here some code
Caller
public async void Caller_Click(){
await jsonDataClass.DoOperations();
}
The method in the jsonDataClass
public async Task<bool> DoOperations(){
// do requests and some stuff..
var fetchedElements = getdata(); // not async, because its in a portable lib
foreach (var element in fetchedElements)
OnEvent(element); // raises an event to assing the element to the Bing map
}
Don't ignore compiler warnings. In particular, if you have an async method that doesn't use await, then the compiler will specifically tell you that the method is not asynchronous and will run synchronously.
The first thing I would recommend is to change getdata so that it is async. The Microsoft.Bcl.Async NuGet package extends async support to portable class libraries.
If that's not possible, then you'll have to execute getdata on a background thread, like this:
public async Task<bool> DoOperations()
{
var fetchedElements = await Task.Run(() => getdata());
foreach (var element in fetchedElements)
OnEvent(element);
}
P.S. The term "background task" has a special meaning in WinRT. What you actually need is to run code on a thread pool thread (or background thread), which is different than what WinRT calls a "background task".
Microsoft just announced the new C# Async feature. Every example I've seen so far is about asynchronously downloading something from HTTP. Surely there are other important async things?
Suppose I'm not writing a new RSS client or Twitter app. What's interesting about C# Async for me?
Edit I had an Aha! moment while watching Anders' PDC session. In the past I have worked on programs that used "watcher" threads. These threads sit waiting for something to happen, like watching for a file to change. They aren't doing work, they're just idle, and notify the main thread when something happens. These threads could be replaced with await/async code in the new model.
Ooh, this sounds interesting. I'm not playing with the CTP just yet, just reviewing the whitepaper. After seeing Anders Hejlsberg's talk about it, I think I can see how it could prove useful.
As I understand, async makes writing asynchronous calls easier to read and implement. Very much in the same way writing iterators is easier right now (as opposed to writing out the functionality by hand). This is essential blocking processes since no useful work can be done, until it is unblocked. If you were downloading a file, you cannot do anything useful until you get that file letting the thread go to waste. Consider how one would call a function which you know will block for an undetermined length and returns some result, then process it (e.g., store the results in a file). How would you write that? Here's a simple example:
static object DoSomeBlockingOperation(object args)
{
// block for 5 minutes
Thread.Sleep(5 * 60 * 1000);
return args;
}
static void ProcessTheResult(object result)
{
Console.WriteLine(result);
}
static void CalculateAndProcess(object args)
{
// let's calculate! (synchronously)
object result = DoSomeBlockingOperation(args);
// let's process!
ProcessTheResult(result);
}
Ok good, we have it implemented. But wait, the calculation takes minutes to complete. What if we wanted to have an interactive application and do other things while the calculation took place (such as rendering the UI)? This is no good, since we called the function synchronously and we have to wait for it to finish effectively freezing the application since the thread is waiting to be unblocked.
Answer, call the function expensive function asynchronously. That way we're not bound to waiting for the blocking operation to complete. But how do we do that? We'd call the function asynchronously and register a callback function to be called when unblocked so we may process the result.
static void CalculateAndProcessAsyncOld(object args)
{
// obtain a delegate to call asynchronously
Func<object, object> calculate = DoSomeBlockingOperation;
// define the callback when the call completes so we can process afterwards
AsyncCallback cb = ar =>
{
Func<object, object> calc = (Func<object, object>)ar.AsyncState;
object result = calc.EndInvoke(ar);
// let's process!
ProcessTheResult(result);
};
// let's calculate! (asynchronously)
calculate.BeginInvoke(args, cb, calculate);
}
Note: Sure we could start another thread to do this but that would mean we're spawning a thread that just sits there waiting to be unblocked, then do some useful work. That would be a waste.
Now the call is asynchronous and we don't have to worry about waiting for the calculation to finish and process, it's done asynchronously. It will finish when it can. An alternative to calling code asynchronously directly, you could use a Task:
static void CalculateAndProcessAsyncTask(object args)
{
// create a task
Task<object> task = new Task<object>(DoSomeBlockingOperation, args);
// define the callback when the call completes so we can process afterwards
task.ContinueWith(t =>
{
// let's process!
ProcessTheResult(t.Result);
});
// let's calculate! (asynchronously)
task.Start();
}
Now we called our function asynchronously. But what did it take to get it that way? First of all, we needed the delegate/task to be able to call it asynchronously, we needed a callback function to be able to process the results, then call the function. We've turned a two line function call to much more just to call something asynchronously. Not only that, the logic in the code has gotten more complex then it was or could be. Although using a task helped simplify the process, we still needed to do stuff to make it happen. We just want to run asynchronously then process the result. Why can't we just do that? Well now we can:
// need to have an asynchronous version
static async Task<object> DoSomeBlockingOperationAsync(object args)
{
//it is my understanding that async will take this method and convert it to a task automatically
return DoSomeBlockingOperation(args);
}
static async void CalculateAndProcessAsyncNew(object args)
{
// let's calculate! (asynchronously)
object result = await DoSomeBlockingOperationAsync(args);
// let's process!
ProcessTheResult(result);
}
Now this was a very simplified example with simple operations (calculate, process). Imagine if each operation couldn't conveniently be put into a separate function but instead have hundreds of lines of code. That's a lot of added complexity just to gain the benefit of asynchronous calling.
Another practical example used in the whitepaper is using it on UI apps. Modified to use the above example:
private async void doCalculation_Click(object sender, RoutedEventArgs e) {
doCalculation.IsEnabled = false;
await DoSomeBlockingOperationAsync(GetArgs());
doCalculation.IsEnabled = true;
}
If you've done any UI programming (be it WinForms or WPF) and attempted to call an expensive function within a handler, you'll know this is handy. Using a background worker for this wouldn't be that much helpful since the background thread will be sitting there waiting until it can work.
Suppose you had a way to control some external device, let's say a printer. And you wanted to restart the device after a failure. Naturally it will take some time for the printer to start up and be ready for operation. You might have to account for the restart not helping and attempt to restart again. You have no choice but to wait for it. Not if you did it asynchronously.
static async void RestartPrinter()
{
Printer printer = GetPrinter();
do
{
printer.Restart();
printer = await printer.WaitUntilReadyAsync();
} while (printer.HasFailed);
}
Imagine writing the loop without async.
One last example I have. Imagine if you had to do multiple blocking operations in a function and wanted to call asynchronously. What would you prefer?
static void DoOperationsAsyncOld()
{
Task op1 = new Task(DoOperation1Async);
op1.ContinueWith(t1 =>
{
Task op2 = new Task(DoOperation2Async);
op2.ContinueWith(t2 =>
{
Task op3 = new Task(DoOperation3Async);
op3.ContinueWith(t3 =>
{
DoQuickOperation();
}
op3.Start();
}
op2.Start();
}
op1.Start();
}
static async void DoOperationsAsyncNew()
{
await DoOperation1Async();
await DoOperation2Async();
await DoOperation3Async();
DoQuickOperation();
}
Read the whitepaper, it actually has a lot of practical examples like writing parallel tasks and others.
I can't wait to start playing with this either in the CTP or when .NET 5.0 finally makes it out.
The main scenarios are any scenario that involves high latency. That is, lots of time between "ask for a result" and "obtain a result". Network requests are the most obvious example of high latency scenarios, followed closely by I/O in general, and then by lengthy computations that are CPU bound on another core.
However, there are potentially other scenarios that this technology will mesh nicely with. For example, consider scripting the logic of a FPS game. Suppose you have a button click event handler. When the player clicks the button you want to play a siren for two seconds to alert the enemies, and then open the door for ten seconds. Wouldn't it be nice to say something like:
button.Disable();
await siren.Activate();
await Delay(2000);
await siren.Deactivate();
await door.Open();
await Delay(10000);
await door.Close();
await Delay(1000);
button.Enable();
Each task gets queued up on the UI thread, so nothing blocks, and each one resumes the click handler at the right point after its job is finished.
I've found another nice use-case for this today: you can await user interaction.
For example, if one form has a button that opens another form:
Form toolWindow;
async void button_Click(object sender, EventArgs e) {
if (toolWindow != null) {
toolWindow.Focus();
} else {
toolWindow = new Form();
toolWindow.Show();
await toolWindow.OnClosed();
toolWindow = null;
}
}
Granted, this isn't really any simpler than
toolWindow.Closed += delegate { toolWindow = null; }
But I think it nicely demonstrates what await can do. And once the code in the event handler is non-trivial, await make programming much easier. Think about the user having to click a sequence of buttons:
async void ButtonSeries()
{
for (int i = 0; i < 10; i++) {
Button b = new Button();
b.Text = i.ToString();
this.Controls.Add(b);
await b.OnClick();
this.Controls.Remove(b);
}
}
Sure, you could do this with normal event handlers, but it would require you to take apart the loop and convert it into something much harder to understand.
Remember that await can be used with anything that gets completed at some point in the future. Here's the extension method Button.OnClick() to make the above work:
public static AwaitableEvent OnClick(this Button button)
{
return new AwaitableEvent(h => button.Click += h, h => button.Click -= h);
}
sealed class AwaitableEvent
{
Action<EventHandler> register, deregister;
public AwaitableEvent(Action<EventHandler> register, Action<EventHandler> deregister)
{
this.register = register;
this.deregister = deregister;
}
public EventAwaiter GetAwaiter()
{
return new EventAwaiter(this);
}
}
sealed class EventAwaiter
{
AwaitableEvent e;
public EventAwaiter(AwaitableEvent e) { this.e = e; }
Action callback;
public bool BeginAwait(Action callback)
{
this.callback = callback;
e.register(Handler);
return true;
}
public void Handler(object sender, EventArgs e)
{
callback();
}
public void EndAwait()
{
e.deregister(Handler);
}
}
Unfortunately it doesn't seem possible to add the GetAwaiter() method directly to EventHandler (allowing await button.Click;) because then the method wouldn't know how to register/deregister that event.
It's a bit of boilerplate, but the AwaitableEvent class can be re-used for all events (not just UI). And with a minor modification and adding some generics, you could allow retrieving the EventArgs:
MouseEventArgs e = await button.OnMouseDown();
I could see this being useful with some more complex UI gestures (drag'n'drop, mouse gestures, ...) - though you'd have to add support for cancelling the current gesture.
There are some samples and demos in the CTP that don't use the Net, and even some that don't do any I/O.
And it does apply to all multithreaded / parallel problem areas (that already exist).
Async and Await are a new (easier) way of structuring all parallel code, be it CPU-bound or I/O bound. The biggest improvement is in areas where before C#5 you had to use the APM (IAsyncResult) model, or the event model (BackgroundWorker, WebClient). I think that is why those examples lead the parade now.
A GUI clock is a good example; say you want to draw a clock, that updates the time shown every second. Conceptually, you want to write
while true do
sleep for 1 second
display the new time on the clock
and with await (or with F# async) to asynchronously sleep, you can write this code to run on the UI thread in a non-blocking fashion.
http://lorgonblog.wordpress.com/2010/03/27/f-async-on-the-client-side/
The async extensions are useful in some cases when you have an asynchronous operation. An asynchronous operation has a definite start and completion. When asynchronous operations complete, they may have a result or an error. (Cancellation is treated as a special kind of error).
Asynchronous operations are useful in three situations (broadly speaking):
Keeping your UI responsive. Any time you have a long-running operation (whether CPU-bound or I/O-bound), make it asynchronous.
Scaling your servers. Using asynchronous operations judiciously on the server side may help your severs to scale. e.g., asynchronous ASP.NET pages may make use of async operations. However, this is not always a win; you need to evaluate your scalability bottlenecks first.
Providing a clean asynchronous API in a library or shared code. async is excellent for reusability.
As you begin to adopt the async way of doing things, you'll find the third situation becoming more common. async code works best with other async code, so asynchronous code kind of "grows" through the codebase.
There are a couple of types of concurrency where async is not the best tool:
Parallelization. A parallel algorithm may use many cores (CPUs, GPUs, computers) to solve a problem more quickly.
Asynchronous events. Asynchronous events happen all the time, independent of your program. They often do not have a "completion." Normally, your program will subscribe to an asynchronous event stream, receive some number of updates, and then unsubscribe. Your program can treat the subscribe and unsubscribe as a "start" and "completion", but the actual event stream never really stops.
Parallel operations are best expressed using PLINQ or Parallel, since they have a lot of built-in support for partitioning, limited concurrency, etc. A parallel operation may easily be wrapped in an awaitable by running it from a ThreadPool thread (Task.Factory.StartNew).
Asynchronous events do not map well to asynchronous operations. One problem is that an asynchronous operation has a single result at its point of completion. Asynchronous events may have any number of updates. Rx is the natural language for dealing with asynchronous events.
There are some mappings from an Rx event stream to an asynchronous operation, but none of them are ideal for all situations. It's more natural to consume asynchronous operations by Rx, rather than the other way around. IMO, the best way of approaching this is to use asynchronous operations in your libraries and lower-level code as much as possible, and if you need Rx at some point, then use Rx from there on up.
Here is probably a good example of how not to use the new async feature (that's not writing a new RSS client or Twitter app), mid-method overload points in a virtual method call. To be honest, i am not sure there is any way to create more than a single overload point per method.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace AsyncText
{
class Program
{
static void Main(string[] args)
{
Derived d = new Derived();
TaskEx.Run(() => d.DoStuff()).Wait();
System.Console.Read();
}
public class Base
{
protected string SomeData { get; set; }
protected async Task DeferProcessing()
{
await TaskEx.Run(() => Thread.Sleep(1) );
return;
}
public async virtual Task DoStuff() {
Console.WriteLine("Begin Base");
Console.WriteLine(SomeData);
await DeferProcessing();
Console.WriteLine("End Base");
Console.WriteLine(SomeData);
}
}
public class Derived : Base
{
public async override Task DoStuff()
{
Console.WriteLine("Begin Derived");
SomeData = "Hello";
var x = base.DoStuff();
SomeData = "World";
Console.WriteLine("Mid 1 Derived");
await x;
Console.WriteLine("EndDerived");
}
}
}
}
Output Is:
Begin Derived
Begin Base
Hello
Mid 1 Derived
End Base
World
EndDerived
With certain inheritance hierarchies (namely using command pattern) i find myself wanting to do stuff like this occasionally.
here is an article about showing how to use the 'async' syntax in a non-networked scenario that involves UI and multiple actions.