Why does this task cause a deadlock? [duplicate] - c#

This question already has answers here:
An async/await example that causes a deadlock
(5 answers)
Closed 4 years ago.
.NET 4.7.2 website
using System;
using System.Threading.Tasks;
using System.Web;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
string input = Input.Text;
bool iWantDeadlock = input == "yes";
string key = iWantDeadlock
? GetHashFragmentAsync(input).GetResultSafely()
: Task.Run(() => GetHashFragmentAsync(input)).Result;
Response.Redirect(key);
}
}
private static async Task<string> GetHashFragmentAsync(string key)
{
await Task.Delay(100);
return "#" + HttpUtility.UrlEncode(key);
}
}
public static class TaskExtensions
{
public static T GetResultSafely<T>(this Task<T> task)
{
return Task.Run(() => task).Result;
}
}
I made a very simple page, with a textbox, that puts the input in the hashfragment of the page after submitting it.
I was reading up on Tasks and deadlocks (after I ran into some code from others that was causing one).
The solution seems to be to do this:
Task.Run(() => GetHashFragmentAsync(input)).Result;
So I thought, let's make that an extension for clarity and easy use.
public static class TaskExtensions
{
public static T GetResultSafely<T>(this Task<T> task)
{
return Task.Run(() => task).Result;
}
}
This however causes a deadlock. The code is the same, but works very different.
Can someone explain this behaviour?

Because when you use GetHashFragmentAsync(input).GetResultSafely() you have actually 2 tasks not 1.
GetHashFragmentAsync(input) returns already started task. Then you call GetResultSafely() which creates another task.
When you wait for a task on UI thread you deadlock, because task cannot go back to synchronization context thread. When you have two tasks, then the second task can wait synchronously, because parent task is not on UI thread, but on ThreadPool thread, which doesn't have synchronization context.
When you call any IO based code, you should never call Task.Run. Simply write
protected async void EventHandlerMethod(object sender, EventArgs e)
{
await GetHashFragmentAsync(input);
}
Here is what happens
GetHashFragmentAsync(input) // Start Task number 1
.GetResultSafely() // Start task number 2 from task number 1 (no synchronization context)
// .Result returns back to task 1
Second scenario
Task.Run(() => GetHashFragmentAsync(input)) // UI thread so, capture synchronization context
.Result // Wait for UI thread to finish (deadlock)

When you call GetHashFragmentAsync(input) the current synchronization context is captured by the C# async/await machinery. The method returns a started task which depends on the UI thread. You try to use Task.Run to move that task of the critical UI thread but it's too late.
GetHashFragmentAsync(input) must be called on a non-UI thread already. Wrap it in Task.Run.
Here's a helper method that works by taking a factory:
public static T GetResultSafely<T>(Func<Task<T>> task)
{
return Task.Run(() => task()).Result;
}
The factory is called on the thread pool.
I should say that normally the best solution is to use async APIs through and through, or to stay totally synchronous. Mixing is problematic for correctness and performance reasons. But it absolutely can be done safely.

Related

Executing multiple tasks asynchronously in C#

Environment
Windows 7
Visual Studio
C#
What I'm trying to do
I'm trying to build an app to evaluate company products. For security, the description below is made abstract to some extent.
What this app does is changing a certain parameter in the product and see how a certain value of the product changes. So I need to do two things.
Change the parameter at a certain interval
Display the value in a textbox at a certain interval
The diagram is like this.
These tasks should be repeated until a cancel button is pressed.
The UI has these controls:
button1 : start button
button2 : cancel button
textbox1 : to show values obtained from the device
So here is the code I wrote.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
CancellationTokenSource cts = new CancellationTokenSource();
private async void button1_Click(object sender, EventArgs e)
{
await Task1();
await Task2();
}
private async Task Task1()
{
while (!cts.IsCancellationRequested)
{
Thread.Sleep(500);
ChangeParameter(0);
Thread.Sleep(1000);
ChangeParameter(10);
Thread.Sleep(500);
ChangeParameter(0);
}
}
private void ChangeParameter(double param)
{
// change device paremeter
Console.WriteLine("devicep parameter changed : " + param);
}
private async Task Task2()
{
while (!cts.IsCancellationRequested)
{
Thread.Sleep(100);
int data = GetDataFromDevice();
UpdateTextBoxWithData(data);
}
cts.Token.ThrowIfCancellationRequested();
}
private int GetDataFromDevice()
{
//pseudo code
var rnd = new Random();
return rnd.Next(100);
}
private void UpdateTextBoxWithData(int data)
{
textBox1.AppendText(data.ToString() + "\n");
// debug
Console.WriteLine("data : " + data);
}
private void button2_Click(object sender, EventArgs e)
{
cts.Cancel();
}
}
Issues
However, there are two issues in this code.
UI freezes.
Task2 is never executed.
The second issue is derived from await since it executes tasks one by one. I could have used Task.Run() but this doesn't allow adding values to textBox since it's different from the UI thread.
How can I solve these issues? Any help would be appreciated.
First of all, async methods can be illusive as they won't turn your methods magically asynchronous. Instead, you can consider an async method as a setup for a state machine (see a detailed explanation here), where you schedule the chain of operations by the await calls.
For that reason, your async methods must execute as fast as possible. Do not do any blocking operation in such a setup method. If you have a blocking operation, which you want to execute in the async method, schedule it by an await Task.Run(() => MyLongOperation()); call.
So for example this will return immediately:
private async Task Task1()
{
await Task.Run(() =>
{
while (!cts.IsCancellationRequested)
{
Thread.Sleep(500);
ChangeParameter(0);
Thread.Sleep(1000);
ChangeParameter(10);
Thread.Sleep(500);
ChangeParameter(0);
}
}
}
A small remark: others may suggest to use Task.Delay instead of Thread.Sleep. I would say that use Task.Delay only if it is the part of the configuration of your state machine. But if the delay is intended to be used as a part of the long-lasting operation, which you don't want to split up, you can simply stay at the Thread.Sleep.
Finally, a remark for this part:
private async void button1_Click(object sender, EventArgs e)
{
await Task1();
await Task2();
}
This configures your tasks to be executed after each other. If you want to execute them parallel, do it like this:
private async void button1_Click(object sender, EventArgs e)
{
Task t1 = Task1();
Task t2 = Task2();
await Task.WhenAll(new[] { t1, t2 });
}
Edit: An extra note for long-lasting tasks: By default, Task.Run executes the tasks on pool threads. Scheduling too many parallel and long lasting tasks might cause starvation and the whole application may freeze for long seconds. So for long-lasting operation you might want to use Task.Factory.StartNew with TaskCreationOptions.LongRunning option instead of Task.Run.
// await Task.Run(() => LooongOperation(), token);
await Task.Factory.StartNew(() => LooongOperation(), token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
The problem is you not using await in your tasks so they executing synchronously.
You should use something like this to maintain your UI responsive (NOTE this is not production code, I'm just showing an idea):
private void button1_Click(object sender, EventArgs e)
{
try
{
await Task.WhenAll(Task1(cts.Token), Task2(cts.Token));
}
catch (TaskCancelledException ex)
{
}
}
private async Task Task1(CancellationToken token)
{
while (true)
{
token.ThrowIfCancellationRequested();
await Task.Delay(500, token); // pass token to ensure delay canceled exactly when cancel is pressed
ChangeParameter(0);
await Task.Delay(1000, token);
ChangeParameter(10);
await Task.Delay(500, token);
ChangeParameter(0);
}
}
private async Task Task2(CancellationToken token)
{
while (true)
{
token.ThrowIfCancellationRequested();
await Task.Delay(100, token);
int data = await Task.Run(() => GetDataFromDevice()); //assuming this could be long running operation it shouldn't be on ui thread
UpdateTextBoxWithData(data);
}
}
Basically, when you need to run something on background you should wrap that in Task.Run() and then await for result. Simply adding async to your method won't make this method asynchronous.
To make your code clearer, I suggest you to move methods like GetDataFromDevice or ChangeParameter to services layer. Also, take a look at IProgress as comments suggests to update your UI according to progress of some process.
There are many issues with this code:
async/await doesn't make the code asynchronous automagically. It allows you to await the results of already asynchronous operations. If you want to run something in the background that isn't already asynchronous, you need to use Task.Run or a similar method to start a Task.
await returns execution to the original synchronization context. In this case, the UI thread. By using Thread.Sleep, you are freezing the UI thread
You can't update the UI from another thread and that goes for Tasks too. You can use the IProgress interface though to report progress. A lot of BCL classes use this interface, just like CancellationToken
Maxim Kosov already cleaned up the code and shows how to properly use async/await and Task.Run, so I'll just post how to use IProgress< T> and its impelementation, Progress< T>
IProgress is used to publich a progress update with the IProgress< T>.Report method. Its default implementation, Progress, raises the ProgressChanged event and/or calls the Action<T> passed to its constructor, on the UI thread. Specifically, on the synchronization context captured when the class was created.
You can create a progress object in your constructor or your button click event, eg
private async void button1_Click(object sender, EventArgs e)
{
var progress=new Progress<int>(data=>UpdateTextBoxWithData(data));
//...
//Allow for cancellation of the task itself
var token=cts.Token;
await Task.Run(()=>MeasureInBackground(token,progress),token);
}
private async Task MeasureInBackground(CancellationToken token,IProgress<int> progress)
{
while (!token.IsCancellationRequested)
{
await Task.Delay(100,token);
int data = GetDataFromDevice();
progress.Report(data);
}
}
Note that using Thread.Sleep inside a task is not a good idea because it wastes a threadpool thread doing nothing. It's better to use await Task.Delay() which requires that the signature of the method change to async Task. There is a Task.Run(Func) overload just for this purpose.
The method is a bit different from Maxim Kosov's code to show that IProgress really communicates across threads. IProgress can handle complex classes, so you could return both a progress percentage and a message, eg:
private async Task MeasureInBackground(CancellationToken token,IProgress<Tuple<int,string>> progress)
{
while(!token.IsCancellationRequested)
{
await Task.Delay(100,token);
int data = GetDataFromDevice();
progress.Report(Tuple.Create(data,"Working"));
}
progress.Report(Tuple.Create(-1,"Cancelled!"));
}
Here I'm just being lazy and return a Tuple<int,string>. A specialized progress class would be more appropriate in production code.
The advantage of using an Action is that you don't need to manage event handlers and the objects are local to the async method. Cleanup is performed by .NET itself.
If your device API provides truly asynchronous calls, you don't need Task.Run. This means that you don't have to waste a Task in a tigh loop, eg:
private async Task MeasureInBackground(CancellationToken token,IProgress<Tuple<int,string>> progress)
{
while(!token.IsCancellationRequested)
{
await Task.Delay(100, token);
int data = await GetDataFromDeviceAsync();
progress.Report(Tuple.Create(data,"Working"));
}
progress.Report(Tuple.Create(-1,"Cancelled!"));
}
Most drivers perform IO tasks using an OS feature called completion ports, essentially callbacks that are called when the driver completes an operation. This way they don't need to block while waiting for a network, database or file system response.
EDIT
In the last example, Task.Run is no longer needed. Just using await would be enough:
await MeasureInBackground(token,progress);

What is the best practice for running multiple background tasks

I have a Windows Service (.NET 4.5.2) which should run multiple tasks in the background while I want to use the System.Threading.Tasks which of the following implementation you are considering best practice? Or am I completely wrong?
Scenario 1:
protected override void OnStart(string[] args)
{
// Assume all tasks implemented the same way.
// I believe we shouldn't await the tasks in this scenario.
var token = this._cancellationTokenSource.Token;
this.RunTask1(token);
this.RunTask2(token);
this.RunTask3(token);
}
private async Task RunTask1(CancellationToken token)
{
var telebot = new Telebot("SOMETHING");
while( true )
{
// Some work...
// I/O dependent task.
var response = await telebot.GetUpdatesAsync(cancellationToken: token);
//
// Some other work
// maybe some database calls using EF async operators.
//
await Task.Delay(TimeSpan.FromSeconds(1), token);
}
}
Scenario 2:
protected override void OnStart(string[] args)
{
// Assume all tasks implemented the same way.
// I believe we shouldn't await the tasks in this scenario.
var token = this._cancellationTokenSource.Token;
this.RunTask1(token);
this.RunTask2(token);
this.RunTask3(token);
}
private void RunTask1(CancellationToken token)
{
Task.Factory.StartNew(async () =>
{
var telebot = new Telebot("SOMETHING");
while( true )
{
// Some work...
// I/O dependent task.
var response = await telebot.GetUpdatesAsync(cancellationToken: token);
//
// Some other work
// may be some database calls using EF async operators.
//
await Task.Delay(TimeSpan.FromSeconds(1), token);
}
}, token);
}
I cannot explain which is best one but here is how things work
in 1. scenario code till await keyword is executed by parent Thread i.e. main thread of application. So once execution await task execution completed thing handled by context which is saved i.e. main thread context.
in 2. scenario code it started running on thread which is created by Task Factory. here once execution await task execution completed things handled by parent i.e Thread created by Task Factory.
So in the first scenario is good if you want to post something to main thread mostly to UI of application. Second scenario is good if you want to run thing in background and doesnt need of parent context i.e. main thread or UI thread.
An async method runs synchronously until the first await. After that it will run on a ThreadPool thread (unless there's a SynchronizationContext).
So, using Task.Factory.StartNew or Task.Run is discouraged as it's trying to parallelize something which is mostly already parallel.
If, however, you have a substantial synchronous part it can be useful using Task.Run (which is preferable to Task.Factory.StartNew) to parallelize it, but you should do it when calling the method and not in the method itself.
So, "Scenario 1" is better than "Scenario 2".
I would though that you shouldn't fire and forget these operations. You should store the tasks, wait for them to complete and observe any exceptions inside them, for example:
protected override void OnStart()
{
var token = _cancellationTokenSource.Token;
_tasks.Add(RunTask1(token));
_tasks.Add(RunTask2(token));
_tasks.Add(Task.Run(() => RunTask3(token))); // assuming RunTask3 has a long synchronous part
}
List<Task> _tasks;
protected override void OnStop()
{
_cancellationTokenSource.Cancel();
Task.WhenAll(_tasks).Wait();
}

Deadlock while using async/await

I'm trying to understand await and async.
It works very well. But now I have a deadlock.
I've called ConfigureAwait with false, like in this article, but my code is still blocking.
Here's a little snippet of my code:
private void button1_Click(object sender, EventArgs e)
{
var result = HeavyWorkAsync().Result;
richTextBox1.AppendText(result);
}
private string HeavyWork()
{
for (var index = 0; index < 1000; index++)
{
Task.Delay(10).Wait();
}
return "finished";
}
private async Task<string> HeavyWorkAsync()
{
var task = await Task.Factory.StartNew<string>(HeavyWork).ConfigureAwait(false);
return task;
}
What's blocking is not the task itself, it's the call to Result. A Task represents an asynchronous operation, but calling its Result property, or calling Wait() will block the current thread until the method returns. And in a lot of cases, it will cause a deadlock because the task is not able to complete with it's calling thread blocked!
To prevent that, chain the tasks asynchronously, using async and await
private async void button1_Click(object sender, EventArgs e)
{
var result = await HeavyWorkAsync(); // <=== await
richTextBox1.AppendText(result);
}
Also, Task.Delay(10).Wait(); completely defeats the prupose of using tasks in the first place: that will block the current thread. If that's really what you want to do (and it's pretty unlikely), call Thread.Sleep(10);instead, it will make your intent much clearer, and you will have less hoops to jump through. Or better, use await Task.Delay(10);in an async method.
About ConfigureAwait
What exactly does ConfigureAwait(false) do?
It removes the obligation for the continuation of the task to run in the same context as the caller of the task. In most cases that means that the continuation is no longer guaranteed to run on the same context. So if I have a method thad does Foo(), waits a little then Bar() like this one:
async Task DoStufAsync()
{
Foo();
await Task.Delay(10);
Bar(); // run in the same context as Foo()
}
I'm guaranteed Bar will run in the same context. If I had ConfigureAwait(false), it's no longer the case
async Task DoStufAsync()
{
Foo();
await Task.Delay(10).ConfigureAwait(false);
Bar(); // can run on another thread as Foo()
}
When you're using ConfigureAwait(false), you tell your program you dont mind about the context. It can solve some deadlocking problems, but isn't usually the right solution. The right solution is most likely never to wait for tasks in a blocking way, and being asynchronous all the way.
To expand upon Falanwe's answer, you should check out Stephen Cleary's blog post. Based off of the code I'm assuming that you are using a Windows Forms application, so a call to Task.Result will execute the task on the UI context, which in turn blocks the UI thread.

RunAsync - How do I await the completion of work on the UI thread?

When awaiting Dispatcher.RunAsync the continuation occurs when the work is scheduled, not when the work has completed. How can I await the work completing?
Edit
My original question assumed the premature continuation was caused by the design of the API, so here's the real question.
When awaiting Dispatcher.RunAsync using an asynchronous delegate, using await within the delegate's code, the continuation occurs when the await is encountered, not when the work has completed. How can I await the work completing?
Edit 2
One reason you may need to dispatch work that's already on the UI thread is to workaround subtle timing and layout issues. It's quite common for values of sizes and positions of elements in the visual tree to be in flux and scheduling work for a later iteration of the UI can help.
I found the following suggestion on a Microsoft github repository: How to await a UI task sent from a background thread.
Setup
Define this extension method for the CoreDispatcher:
using System;
using System.Threading.Tasks;
using Windows.UI.Core;
public static class DispatcherTaskExtensions
{
public static async Task<T> RunTaskAsync<T>(this CoreDispatcher dispatcher,
Func<Task<T>> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal)
{
var taskCompletionSource = new TaskCompletionSource<T>();
await dispatcher.RunAsync(priority, async () =>
{
try
{
taskCompletionSource.SetResult(await func());
}
catch (Exception ex)
{
taskCompletionSource.SetException(ex);
}
});
return await taskCompletionSource.Task;
}
// There is no TaskCompletionSource<void> so we use a bool that we throw away.
public static async Task RunTaskAsync(this CoreDispatcher dispatcher,
Func<Task> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) =>
await RunTaskAsync(dispatcher, async () => { await func(); return false; }, priority);
}
Once you do that, all you need to do is use the new RunTaskAsync method to have your background task await on the UI work.
Usage example
Let's pretend that this is the method that needs to run in the UI thread. Pay attention to the debug statements, which will help follow the flow:
public static async Task<string> ShowMessageAsync()
{
// Set up a MessageDialog
var popup = new Windows.UI.Popups.MessageDialog("Question", "Please pick a button to continue");
popup.Commands.Add(new Windows.UI.Popups.UICommand("Button 1"));
popup.Commands.Add(new Windows.UI.Popups.UICommand("Button 2"));
popup.CancelCommandIndex = 0;
// About to show the dialog
Debug.WriteLine("Waiting for user choice...");
var command = await popup.ShowAsync();
// Dialog has been dismissed by the user
Debug.WriteLine("User has made a choice. Returning result.");
return command.Label;
}
To await that from your background thread, this is how you would use RunTaskAsync:
// Background thread calls this method
public async void Object_Callback()
{
Debug.WriteLine("Object_Callback() has been called.");
// Do the UI work, and await for it to complete before continuing execution
var buttonLabel = await Dispatcher.RunTaskAsync(ShowMessageAsync);
Debug.WriteLine($"Object_Callback() is running again. User clicked {buttonLabel}.");
}
The output then looks like this:
Object_Callback() has been called.
Waiting for user choice...
User has made a choice. Returning result.
Object_Callback() is running again. User clicked Button 1.
Your question is assuming that you want to schedule (and wait for) work on a UI thread from a background thread.
You'll usually find your code is much cleaner and easier to understand (and it will definitely be more portable) if you have the UI be the "master" and the background threads be the "slaves".
So, instead of having a background thread await some operation for the UI thread to do (using the awkward and unportable Dispatcher.RunAsync), you'll have the UI thread await some operation for the background thread to do (using the portable, made-for-async Task.Run).
You can wrap the call to RunAsync in your own asynchronous method that can be awaited and control the completion of the task and thus the continuation of awaiting callers yourself.
Since async-await is centred on the Task type, you must orchestrate the work using this type. However, usually a Task schedules itself to run on a threadpool thread and so it cannot be used to schedule UI work.
However, the TaskCompletionSource type was invented to act as a kind of puppeteer to an unscheduled Task. In other words, a TaskCompletionSource can create a dummy Task that is not scheduled to do anything, but via methods on the TaskCompletionSource can appear to be running and completing like a normal job.
See this example.
public Task PlayDemoAsync()
{
var completionSource = new TaskCompletionSource<bool>();
this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
{
try
{
foreach (var ppc in this.Plots.Select(p => this.TransformPlot(p, this.RenderSize)))
{
// For each subsequent stroke plot, we need to start a new figure.
//
if (this.Sketch.DrawingPoints.Any())
this.Sketch.StartNewFigure(ppc.First().Position);
foreach (var point in ppc)
{
await Task.Delay(100);
this.Sketch.DrawingPoints.Add(point.Position);
}
}
completionSource.SetResult(true);
}
catch (Exception e)
{
completionSource.SetException(e);
}
});
return (Task)completionSource.Task;
}
Note: the main work being done on the UI thread is just some lines being drawn on screen every 100ms.
A TaskCompletionSource is created as the puppet master. Look near the end and you'll see that it has a Task property that is returned to the caller. Returning Task satisfies the compilers needs and makes the method awaitable and asynchronous.
However, the Task is just a puppet, a proxy for the actual work going on in the UI thread.
See how in that main UI delegate I use the TaskCompletionSource.SetResult method to force a result into the Task (since returned to the caller) and communicate that work has finished.
If there's an error, I use SetException to 'pull another string' and make it appear that an exception has bubbled-up in the puppet Task.
The async-await subsystem knows no different and so it works as you'd expect.
Edit
As prompted by svick, if the method was designed to be callable only from the UI thread, then this would suffice:
/// <summary>
/// Begins a demonstration drawing of the asterism.
/// </summary>
public async Task PlayDemoAsync()
{
if (this.Sketch != null)
{
foreach (var ppc in this.Plots.Select(p => this.TransformPlot(p, this.RenderSize)))
{
// For each subsequent stroke plot, we need to start a new figure.
//
if (this.Sketch.DrawingPoints.Any())
this.Sketch.StartNewFigure(ppc.First().Position);
foreach (var point in ppc)
{
await Task.Delay(100);
this.Sketch.DrawingPoints.Add(point.Position);
}
}
}
}
A nice way to work the clean way #StephenCleary suggests even if you have to start from a worker thread for some reason, is to use a simple helper object. With the object below you can write code like this:
await DispatchToUIThread.Awaiter;
// Now you're running on the UI thread, so this code is safe:
this.textBox.Text = text;
In your App.OnLaunched you have to initialize the object:
DispatchToUIThread.Initialize(rootFrame.Dispatcher);
The theory behind the code below you can find at await anything;
public class DispatchToUIThread : INotifyCompletion
{
private readonly CoreDispatcher dispatcher;
public static DispatchToUIThread Awaiter { get; private set; }
private DispatchToUIThread(CoreDispatcher dispatcher)
{
this.dispatcher = dispatcher;
}
[CLSCompliant(false)]
public static void Initialize(CoreDispatcher dispatcher)
{
if (dispatcher == null) throw new ArgumentNullException("dispatcher");
Awaiter = new DispatchToUIThread(dispatcher);
}
public DispatchToUIThread GetAwaiter()
{
return this;
}
public bool IsCompleted
{
get { return this.dispatcher.HasThreadAccess; }
}
public async void OnCompleted(Action continuation)
{
if (continuation == null) throw new ArgumentNullException("continuation");
await this.dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => continuation());
}
public void GetResult() { }
}

What's the new C# await feature do? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Can anyone explain what the await function does?
They just talked about this at PDC yesterday!
Await is used in conjunction with Tasks (parallel programming) in .NET. It's a keyword being introduced in the next version of .NET. It more or less lets you "pause" the execution of a method to wait for the Task to complete execution. Here's a brief example:
//create and run a new task
Task<DataTable> dataTask = new Task<DataTable>(SomeCrazyDatabaseOperation);
//run some other code immediately after this task is started and running
ShowLoaderControl();
StartStoryboard();
//this will actually "pause" the code execution until the task completes. It doesn't lock the thread, but rather waits for the result, similar to an async callback
// please so also note, that the task needs to be started before it can be awaited. Otherwise it will never return
dataTask.Start();
DataTable table = await dataTask;
//Now we can perform operations on the Task result, as if we're executing code after the async operation completed
listBoxControl.DataContext = table;
StopStoryboard();
HideLoaderControl();
Basically, the async and await keywords allow you to specify that execution of a method should stop at all usages of await, which mark asynchronous method calls, and then resume once the asynchronous operation is complete. This allows you to call a method in an app's main thread and handle complex work asynchronously, without the need to explicitly define threads and joins or blocking the app's main thread.
Think of it as being somewhat similar to a yield return statement in a method producing an IEnumerable. When the runtime hits the yield, it will basically save the method's current state, and return the value or reference being yielded. The next time IEnumerator.MoveNext() is called on the return object (which is generated internally by the runtime), the method's old state is restored to the stack and execution continues with the next line after the yield return as if we'd never left the method. Without this keyword, an IEnumerator type must be custom-defined to store state and handle the iteration requests, with methods that can become VERY complex indeed.
Similarly, a method marked as async must have at least one await. On an await, the runtime will save the current thread's state and call stack, make the asynchronous call, and unwind back to the runtime's message loop to handle the next message and keep the app responsive. When the asynchronous operation is complete, at the next scheduling opportunity, the call stack to up the async operation is pushed back in and continued as if the call was synchronous.
So, these two new keywords basically simplify the coding of asynchronous processes, much like yield return simplified the generation of custom enumerables. With a couple keywords and a little background knowledge, you can skip all the confusing and often error-prone details of a traditional asynchronous pattern. This will be INVALUABLE in pretty much any event-driven GUI app like Winforms, WPF of Silverlight.
The currently accepted answer is misleading.
await is not pausing anything.
First of all it can be used only in methods or lambdas marked as async and returning Task or void if you don't care having Task instance running in this method.
Here is an illustration:
internal class Program
{
private static void Main(string[] args)
{
var task = DoWork();
Console.WriteLine("Task status: " + task.Status);
Console.WriteLine("Waiting for ENTER");
Console.ReadLine();
}
private static async Task DoWork()
{
Console.WriteLine("Entered DoWork(). Sleeping 3");
// imitating time consuming code
// in a real-world app this should be inside task,
// so method returns fast
Thread.Sleep(3000);
await Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("async task iteration " + i);
// imitating time consuming code
Thread.Sleep(1000);
}
});
Console.WriteLine("Exiting DoWork()");
}
}
Output:
Entered DoWork(). Sleeping 3
async task iteration 0
Task status: WaitingForActivation
Waiting for ENTER
async task iteration 1
async task iteration 2
async task iteration 3
async task iteration 4
async task iteration 5
async task iteration 6
async task iteration 7
async task iteration 8
async task iteration 9
Exiting DoWork()
For anyone new to asynchronous programming in .NET, here's a (totally fake) analogy in a scenario you may be more familiar with - AJAX calls using JavaScript/jQuery. A simple jQuery AJAX post looks like this:
$.post(url, values, function(data) {
// AJAX call completed, do something with returned data here
});
The reason we process the results in a callback function is so we don't block the current thread while waiting for the AJAX call to return. Only when the response is ready will the callback get fired, freeing the current thread to do other things in the mean time.
Now, if JavaScript supported the await keyword (which of course it doesn't (yet!)), you could achieve the same with this:
var data = await $.post(url, values);
// AJAX call completed, do something with returned data here
That's a lot cleaner, but it sure looks like we introduced synchronous, blocking code. But the (fake) JavaScript compiler would have taken everything after await and wired it into a callback, so at runtime the second example would behave just like the first.
It may not seem like it's saving you much work, but when it comes to things like exception handling and synchronization contexts, the compiler is actually doing a lot of heavy lifting for you. For more, I'd recommend the FAQs followed by Stephen Cleary's blog series.
If I had to implement it in Java it would look some thing like this:
/**
* #author Ilya Gazman
*/
public abstract class SynchronizedTask{
private ArrayList<Runnable> listeners = new ArrayList<Runnable>();
private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(6, 6, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1000));
public final void await(Runnable listener){
synchronized (this) {
listeners.add(listener);
}
}
public void excecute(){
onExcecute();
for (int i = listeners.size() - 1; i >= 0; i--) {
Runnable runnable;
synchronized (this) {
runnable = listeners.remove(i);
}
threadPoolExecutor.execute(runnable);
}
}
protected abstract void onExcecute();
}
Your application would use it like this:
public class Test{
private Job job = new Job();
public Test() {
craeteSomeJobToRunInBackground();
methode1();
methode2();
}
private void methode1(){
System.out.println("Running methode 1");
job.await(new Runnable() {
#Override
public void run() {
System.out.println("Continue to running methode 1");
}
});
}
private void methode2(){
System.out.println("Running methode 2");
}
private void craeteSomeJobToRunInBackground() {
new Thread(new Runnable() {
#Override
public void run() {
job.excecute();
}
}).start();
}
private class Job extends SynchronizedTask{
#Override
protected void onExcecute() {
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Job is done");
}
}
}

Categories

Resources