Assume I have a library as follows for both non-UI based apps (ASP.NET) and UI based apps (WinForm and WPF). Unfortunately I cannot avoid mixing IO-bound work and CPU-bound work but I let the consumers invoke DummyWorkAsync via Task.Run or not based on their application types (non-UI or UI based apps).
class DummyService
{
public static async Task<int> DummyWorkAsync()
{
// Do some I/O first.
await Task.Delay(1000);
// Tons of work to do in here!
for (int i = 0; i != 10000000; ++i)
;
// Possibly some more I/O here.
await Task.Delay(1000);
// More work.
for (int i = 0; i != 10000000; ++i)
;
return 0;
}
}
This allows UI-based consumer to properly use Task.Run to call the service, while ASP.NET clients would just call the method directly as follows.
private async void MyButton_Click(object sender, EventArgs e)
{
await Task.Run(() => DummyService.DummyWorkAsync());
}
public class Home: Controller
{
public async Task<ActionResult> IndexAsync()
{
var result = await DummyService.DummyWorkAsync();
return View(result);
}
}
Question
I am interested in the UI-based apps. Is there any difference if I use
private async void MyButton_Click(object sender, EventArgs e)
{
await Task.Run(async () => await DummyService.DummyWorkAsync());
}
rather than
private async void MyButton_Click(object sender, EventArgs e)
{
await Task.Run(() => DummyService.DummyWorkAsync());
}
?
No, there is no (significant) difference. You are basically asking what's the difference between
static Task<int> Something() {
return SomethingAsync();
}
and
static async Task<int> Something() {
return await SomethingAsync();
}
Except in your case there is one more wrapping task (Task.Run), so differences in exceptions propagation for example which you may find in another questions on the same issue are not relevant in this case.
Because of that - just use
await Task.Run(() => DummyService.DummyWorkAsync());
That said, reasons for doing that are not that clear. Since your IO goes first - you can use ConfigureAwait(false) to prevent returning control to current synchronization context (which is good practice for libraries anyway). In that case, after your first await the rest (heavy CPU work) will be executed on thread pool thread (with default scheduler at least), so you won't need to use Task.Run in the first place:
public static async Task<int> DummyWorkAsync()
{
// Do some I/O first.
await Task.Delay(1000).ConfigureAwait(false);
// Tons of work to do in here!
// no problem, we are not on UI thread anyway
for (int i = 0; i != 10000000; ++i)
;
// Possibly some more I/O here.
await Task.Delay(1000).ConfigureAwait(false);
// More work.
for (int i = 0; i != 10000000; ++i)
;
return 0;
}
Related
This question already has answers here:
What's the difference between returning void and returning a Task?
(4 answers)
Closed 3 years ago.
I have the following code:
public static async void PopulateMetrics()
{
await Task.Run(() =>
{
if (App.CPUSpeed == 0)
{
var stopWatch = Stopwatch.StartNew();
stopWatch.Start();
ArrayList al = new ArrayList(); for (int i = 0; i < 5000000; i++) al.Add("hello");
App.CPUSpeed = 20000 / stopWatch.ElapsedMilliseconds;
}
});
}
The IDE is telling me that the async method should not return void. Would making it return Task<bool> and returning true fix this but is that needed?
Also would there be any difference in calling this between:
_ = PopulateMetrics()
and
await PopulateMetrics()
Here is what I have for the calling method. Note that for all except the PopulateMetrics, I have exception handling in each of the async methods.
if (Connectivity.NetworkAccess == NetworkAccess.Internet)
{
if (Settings.Rev == REV.No && (new[] { 15, 30, 50 }).Contains(Settings.Trk2))
{
_ = ReviewAppAsync(Settings.Trk2);
}
if (App.devIsPhysical && (new[] { 10, 20, 30 }).Contains(Settings.Trk2))
{
_ = CheckLatestVersion();
}
_ = Helper.PopulateMetrics();
_ = Helper.LogStart();
}
As a rule, when a non-async method returns void, its async counterpart should return Task:
public static async Task PopulateMetrics()
According to Microsoft, you should use void return from async methods only when you implement an event handler:
Void-returning async methods have a specific purpose: to make asynchronous event handlers possible. It is possible to have an event handler that returns some actual type, but that doesn't work well with the language; invoking an event handler that returns a type is very awkward, and the notion of an event handler actually returning something doesn't make much sense. Event handlers naturally return void, so async methods return void so that you can have an asynchronous event handler.
1) Normally, you would want to return a Task. The main exception should be when you need to have a void return type (for events). If there's no reason to disallow having the caller await your task, why disallow it?
2) async methods that return void are special in another aspect: they represent top-level async operations, and have additional rules that come into play when your task returns an exception. The easiest way is to show the difference is with an example:
static async void f()
{
await h();
}
static async Task g()
{
await h();
}
static async Task h()
{
throw new NotImplementedException();
}
private void button1_Click(object sender, EventArgs e)
{
f();
}
private void button2_Click(object sender, EventArgs e)
{
g();
}
private void button3_Click(object sender, EventArgs e)
{
GC.Collect();
}
f's exception is always "observed". An exception that leaves a top-level asynchronous method is simply treated like any other unhandled exception. g's exception is never observed. When the garbage collector comes to clean up the task, it sees that the task resulted in an exception, and nobody handled the exception. When that happens, the TaskScheduler.UnobservedTaskException handler runs. You should never let this happen. To use your example,
public static async void AsyncMethod2(int num)
{
await Task.Factory.StartNew(() => Thread.Sleep(num));
}
Yes, use async and await here, they make sure your method still works correctly if an exception is thrown.
for more information see: http://msdn.microsoft.com/en-us/magazine/jj991977.aspx
Just set the return type to Task to get rid of the IDE warning:
public static async Task PopulateMetrics()
{
await Task.Run(() =>
{
if (App.CPUSpeed == 0)
{
var stopWatch = Stopwatch.StartNew();
stopWatch.Start();
ArrayList al = new ArrayList(); for (int i = 0; i < 5000000; i++) al.Add("hello");
App.CPUSpeed = 20000 / stopWatch.ElapsedMilliseconds;
}
});
}
Regarding the differences in the two calls, you must think that calling an async method is like starting a new Thread: the current thread is not blocked until the task is awaited or is asked for its's result.
Consider this code:
class Program
{
static async Task Main() // Compiler will warn you 'cause you're not awaiting!
{
_ = PopulateMetrics();
// do something else
}
}
Chances are the program will exit before the PopulateMetrics task has finished.
Since PopulateMetrics returns async Task, you should do:
class Program
{
static async Task Main()
{
var popMetricsTask = PopulateMetrics();
// do something else
popMetricsTask.Wait(); // or: await popMetricsTask;
}
}
To be sure your task has finished before exiting program.
I've started to dive into aync programming and I want to execute a very simple add method as an async operation.
One of the things i've read is that truly async program does not require thread switching => that means Task.Run(..) can be avoided.
This is how I've implemented an add method:
public class TaskSimpleExample
{
public static void SimpleCalcExample()
{
// Will perform in background
Task<int> resultTask = Task.Run(() => BeginCalcNumbers(6, 6));
Console.WriteLine("Doing Work");
Console.WriteLine("Doing More Work");
Console.WriteLine("Doing Extra Work");
resultTask.Wait();
Console.WriteLine("Work is done!");
}
static int BeginCalcNumbers(int number1, int number2)
{
int result = Add(number1, number2);
Console.WriteLine(result);
return result;
}
static int Add(int number1, int number2)
{
int result = number1 + number2;
return result;
}
}
Unfortunately, I understand that it has nothing to do with async. It just opens another thread and runs in the background.
I've failed to convert this code to use async & await (and eliminate Task.Run). Is it possible ? (Please notice I need to continue after the callback in other place in the method using resultTask.Wait()).
What you know about Task.Run is absolutely correct and that's pretty much the point of using Task.Run
Using Task.Run will execute a method on a thread pool thread and return a task that represents the completion of the method.
As Stepthen Cleary suggest, you should use Task.Run only to call CPU-bound methods.
Another important thing to mention is that you should use Task.Run to actually call the method that does heavy CPU-bound work and not use Task.Run in the implementation of the method.
Here's a good example on how to use Task.Run properly:
class MyService
{
public int CalculateMandelbrot()
{
// Tons of work to do in here!
for (int i = 0; i != 10000000; ++i)
;
return 42;
}
}
...
private async void MyButton_Click(object sender, EventArgs e)
{
await Task.Run(() => myService.CalculateMandelbrot());
}
Also you should read Task.Run Etiquette and Proper Usage and Task.Run Etiquette Examples: Don't Use Task.Run in the Implementation if you are interested in learning more about Task.Run
I wrote a visual studio 2015 c# program for reading from a custom Ethernet device some data. I need to use async await instructions because the data will be read all together on scheduled times.
I use a custom .NET library for read data; this is my code:
private void timerPollingData_Tick(object sender, EventArgs e)
{
readDevice_01();
readDevice_02();
// and so on for all devices ...
}
private async void readDevice_01()
{
var result = await getDataDevice_01();
// Save data
}
private async void readDevice_02()
{
var result = await getDataDevice_02();
// Save data
}
private Task<string> getDataDevice_01()
{
MyCustomLibrary readDevice = new MyCustomLibrary.Master();
return Task.Factory.StartNew(() => readDevice.ReadHoldingRegister(... some parameters ...).ToString());
}
private Task<string> getDataDevice_02()
{
MyCustomLibrary readDevice = new MyCustomLibrary.Master();
return Task.Factory.StartNew(() => readDevice.ReadHoldingRegister(... some parameters ...).ToString());
}
My doubt:
what is the best practice for handle exception of each Task? I need to understand what devices are unplug from Ethernet or switch off and then STOP the TASK used to retrieve data from it.
Thanks a lot in advance for your help.
You should avoid async void; use async Task for everything except async event handlers. For more information, see my article on async best practices.
Also, you should not use StartNew; it's a low-level, very dangerous API with inappropriate default parameter values. Use Task.Run instead of StartNew. For more information, see my blog post on StartNew is dangerous.
I need to use async await instructions because the data will be read all together on scheduled times.
Asynchrony is one form of concurrency, which you can use with Task.Run if your device API does not have asynchronous methods:
private async void timerPollingData_Tick(object sender, EventArgs e)
{
var task1 = readDevice_01();
var task2 = readDevice_02();
// and so on for all devices ...
await Task.WhenAll(task1, task2, ...);
}
private async Task readDevice_01()
{
var result = await Task.Run(() => getDataDevice_01());
// Save data
}
private string getDataDevice_01()
{
MyCustomLibrary readDevice = new MyCustomLibrary.Master();
return readDevice.ReadHoldingRegister(... some parameters ...).ToString();
}
If your API had a ReadHoldingRegisterAsync method, then this would be more naturally expressed as:
private async void timerPollingData_Tick(object sender, EventArgs e)
{
var task1 = readDevice_01Async();
var task2 = readDevice_02Async();
// and so on for all devices ...
await Task.WhenAll(task1, task2, ...);
}
private async Task readDevice_01Async()
{
var result = await getDataDevice_01Async();
// Save data
}
private async Task<string> getDataDevice_01Async()
{
MyCustomLibrary readDevice = new MyCustomLibrary.Master();
var result = await readDevice.ReadHoldingRegisterAsync(... some parameters ...);
return result.ToString();
}
My doubt: what is the best practice for handle exception of each Task? I need to understand what devices are unplug from Ethernet or switch off and then STOP the TASK used to retrieve data from it.
The best practices for getting exceptions from tasks are to await them.
You don't have to worry about stopping a task after it raised an exception. By the time the task reports its exception, it has already stopped.
I am starting to study C# TAP coding. I don't understand why the code is running synchronously
async private void timer1_Tick(object sender, EventArgs e)
{
SyncCount++;
result1.Text = SyncCount.ToString();
AsyncCount = await CountForALongTimeAsync(AsyncCount);
result2.Text = AsyncCount.ToString();
}
async Task<int> CountForALongTimeAsync(int counter)
{
Thread.Sleep(3000);
counter++;
return counter;
}
async Task<int> CountForALongTimeAsync(int counter)
{
What comes next will be executed until the first awaited async call that actually does some waiting (it's possible that a given call could have all it needs to return immediately, e.g. a service that might hit the internet or might return data from a cache, in which case it won't wait).
There are no awaited calls at all, so the Task returned is returned already completed.
Since the calling await CountForALongTimeAsync is awaiting a task that is returned already completed, it runs synchronously.
The method would be better as:
async Task<int> CountForALongTimeAsync(int counter)
{
await Task.Delay(3000);
counter++;
return counter;
}
Incidentally, the pre await way of doing something very (but not entirely) similar would have been:
Task<int> CountForALongTimeAsync(int counter)
{
return Task.Delay(3000).ContinueWith(t =>
{
++counter;
return counter;
});
}
Considering that these are different ideas of "continuing" after a task might or might not give some insight.
In contrast the closest pre-await way of doing what the code in your question does was:
Task<int> CountForALongTimeAsync(int counter)
{
Thread.Sleep(3000);
counter++;
return Task.FromResult(counter); //FromResult returns an already completed task.
}
Every blog post I've read tells you how to consume an asynchronous method in C#, but for some odd reason never explain how to build your own asynchronous methods to consume. So I have this code right now that consumes my method:
private async void button1_Click(object sender, EventArgs e)
{
var now = await CountToAsync(1000);
label1.Text = now.ToString();
}
And I wrote this method that is CountToAsync:
private Task<DateTime> CountToAsync(int num = 1000)
{
return Task.Factory.StartNew(() =>
{
for (int i = 0; i < num; i++)
{
Console.WriteLine("#{0}", i);
}
}).ContinueWith(x => DateTime.Now);
}
Is this, the use of Task.Factory, the best way to write an asynchronous method, or should I write this another way?
I don't recommend StartNew unless you need that level of complexity.
If your async method is dependent on other async methods, the easiest approach is to use the async keyword:
private static async Task<DateTime> CountToAsync(int num = 10)
{
for (int i = 0; i < num; i++)
{
await Task.Delay(TimeSpan.FromSeconds(1));
}
return DateTime.Now;
}
If your async method is doing CPU work, you should use Task.Run:
private static async Task<DateTime> CountToAsync(int num = 10)
{
await Task.Run(() => ...);
return DateTime.Now;
}
You may find my async/await intro helpful.
If you didn't want to use async/await inside your method, but still "decorate" it so as to be able to use the await keyword from outside, TaskCompletionSource.cs:
public static Task<T> RunAsync<T>(Func<T> function)
{
if (function == null) throw new ArgumentNullException(“function”);
var tcs = new TaskCompletionSource<T>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
T result = function();
tcs.SetResult(result);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
From here and here
To support such a paradigm with Tasks, we need a way to retain the Task façade and the ability to refer to an arbitrary asynchronous operation as a Task, but to control the lifetime of that Task according to the rules of the underlying infrastructure that’s providing the asynchrony, and to do so in a manner that doesn’t cost significantly. This is the purpose of TaskCompletionSource.
I saw it's also used in the .NET source, e.g. WebClient.cs:
[HostProtection(ExternalThreading = true)]
[ComVisible(false)]
public Task<string> UploadStringTaskAsync(Uri address, string method, string data)
{
// Create the task to be returned
var tcs = new TaskCompletionSource<string>(address);
// Setup the callback event handler
UploadStringCompletedEventHandler handler = null;
handler = (sender, e) => HandleCompletion(tcs, e, (args) => args.Result, handler, (webClient, completion) => webClient.UploadStringCompleted -= completion);
this.UploadStringCompleted += handler;
// Start the async operation.
try { this.UploadStringAsync(address, method, data, tcs); }
catch
{
this.UploadStringCompleted -= handler;
throw;
}
// Return the task that represents the async operation
return tcs.Task;
}
Finally, I also found the following useful:
I get asked this question all the time. The implication is that there must be some thread somewhere that’s blocking on the I/O call to the external resource. So, asynchronous code frees up the request thread, but only at the expense of another thread elsewhere in the system, right? No, not at all.
To understand why asynchronous requests scale, I’ll trace a (simplified) example of an asynchronous I/O call. Let’s say a request needs to write to a file. The request thread calls the asynchronous write method. WriteAsync is implemented by the Base Class Library (BCL), and uses completion ports for its asynchronous I/O. So, the WriteAsync call is passed down to the OS as an asynchronous file write. The OS then communicates with the driver stack, passing along the data to write in an I/O request packet (IRP).
This is where things get interesting: If a device driver can’t handle an IRP immediately, it must handle it asynchronously. So, the driver tells the disk to start writing and returns a “pending” response to the OS. The OS passes that “pending” response to the BCL, and the BCL returns an incomplete task to the request-handling code. The request-handling code awaits the task, which returns an incomplete task from that method and so on. Finally, the request-handling code ends up returning an incomplete task to ASP.NET, and the request thread is freed to return to the thread pool.
Introduction to Async/Await on ASP.NET
If the target is to improve scalability (rather than responsiveness), it all relies on the existence of an external I/O that provides the opportunity to do that.
One very simple way to make a method asynchronous is to use Task.Yield() method. As MSDN states:
You can use await Task.Yield(); in an asynchronous method to force the
method to complete asynchronously.
Insert it at beginning of your method and it will then return immediately to the caller and complete the rest of the method on another thread.
private async Task<DateTime> CountToAsync(int num = 1000)
{
await Task.Yield();
for (int i = 0; i < num; i++)
{
Console.WriteLine("#{0}", i);
}
return DateTime.Now;
}