3 parallel tasks each awaiting their own result - c#

I would like to try using background workers. I am interesting to use async/await.
I have 3 parallel tasks.
private async void RunDownloadsAsync()
{
Task taskDelay1 = Task.Run(() => Task.Delay(10000));
Task taskDelay2 = Task.Run(() => Task.Delay(15000));
Task taskDelay3 = Task.Run(() => Task.Delay(20000));
await ???
}
Let's assume each of these Tasks changes the value of 3 Labels (label1, label2, label3) on a form when they are done. i.e. all labels are set to "Pending" and when each task is done, their corresponding label value will change to "Finished".
I would like to await each task accordingly so that they each do their own corresponding task. That means if taskDelay1's job is finished set label1's text to "Finished" while taskDelay2 and taskDelay3 are still pending. But if I put 3 awaits there, the program will wait for all of them to finish their task and then continue the rest of the code.
How can I continue the rest of the code in which each label only waits for its own task to finish and then decide what to do?

You should use Task.WhenAll method to wait for all of them and ContinueWith to execute operation when the task is completed.
Task taskDelay1 = Task.Run(() => Task.Delay(10000)).ContinueWith(t => SetLabel());
Task taskDelay2 = Task.Run(() => Task.Delay(15000)).ContinueWith(t => SetLabel());
Task taskDelay3 = Task.Run(() => Task.Delay(20000)).ContinueWith(t => SetLabel());
await Task.WhenAll(taskDelay1, taskDelay2, taskDelay3);

There's an important distinction between parallel and concurrent. Parallel refers to using multiple threads to do CPU-bound work. Parallelism is one form of concurrency, but not the only one. Another form of concurrency is asynchrony, which can do non-CPU-bound work without introducing multiple threads.
In your case, "downloads" imply an I/O-bound operation, which should be done with asynchrony and not parallelism. Check out the HttpClient class for asynchronous downloads. You can use Task.WhenAll for asynchronous concurrency:
private async Task RunDownload1Async()
{
label1.Text = "Pending";
await Task.Delay(10000);
label1.Text = "Finished";
}
private async Task RunDownload2Async()
{
label2.Text = "Pending";
await Task.Delay(15000);
label2.Text = "Finished";
}
private async Task RunDownload3Async()
{
label3.Text = "Pending";
await Task.Delay(20000);
label3.Text = "Finished";
}
private async Task RunDownloadsAsync()
{
await Task.WhenAll(RunDownload1Async(), RunDownload2Async(), RunDownload3Async());
}
This approach avoids creating unnecessary threads and also does not use outdated techniques (ContinueWith, Dispatcher.Invoke). That said, it's not perfect, since the GUI logic is mixed with the operational logic in the RunDownloadNAsync methods. A better approach would be to use IProgress<T> and Progress<T> for updating the UI.

You can use ContinueWith to execute an action after the Task is completed. Note that you might need to call Dispatcher.Invoke in the expression in the ContinueWith to prevent cross-thread calls.
Here is a sample from a WPF application, using Dispatcher.Invoke:
private static async void Async()
{
Task taskDelay1 = Task.Run(() => Task.Delay(1000))
.ContinueWith(x => Dispatcher.Invoke(() => this.label1.Content = "One done"));
Task taskDelay2 = Task.Run(() => Task.Delay(1500))
.ContinueWith(x => Dispatcher.Invoke(() => this.label2.Content = "Two done"));
Task taskDelay3 = Task.Run(() => Task.Delay(2000))
.ContinueWith(x => Dispatcher.Invoke(() => this.label3.Content = "Three done"));
await Task.WhenAll(taskDelay1, taskDelay2, taskDelay3);
}
As Dirk suggested, an alternative to calling Dispatcher.Invoke would be to use a task scheduler, e.g. TaskScheduler.FromCurrentSynchronizationContext() if you're on the UI thread.

Related

Running a task periodically without blocking the main thread C#

I am trying to send a keep-alive HTTP request each 30 minutes. However I have other methods to be called at the time in between, so what I tried to do is:
Task.Factory.StartNew(async () =>
{
while(true){
await Task.Delay(new TimeSpan(0,30,0), CancellationToken.None);
await FooTask();
}
});
Am I using it properly?
Are you doing it properly? No. You say you want a loop, but don't write a loop. You're also using the wrong task creation function:
Task.Run(async () =>
{
while(true)
{
await FooTask().ConfigureAwait(false);
await Task.Delay(new TimeSpan(0, 30, 0)).ConfigureAwait(false);
}
});
There's also PeriodicTimer which follows a similar pattern, you do your action and await the next tick.
I'd suggest using Microsoft's Reactive Framework.
Then you can just do this:
IDisposable subscription =
Observable
.Timer(TimeSpan.Zero, TimeSpan.FromMinutes(30.0))
.SelectMany(_ => Observable.FromAsync(() => FooTask()))
.Subscribe();
Calling subscription.Dispose() shuts it down. It's nice and simple.
You likely want to use Task.Run() instead of Task.Factory.StartNewAsync(), per the remarks in the docs. Task.Run() is recommended unless you need the extra options in Task.Factory.StartNewAsync() (ex: Task Creation Options, Task Scheduler, Parameter Passing that Task.Run() does not cover).
Task.Run() will queue the task to run on the current thread pool, and it will also return a handle to the task in case you want to Wait for completion or Cancel the task, as shown in the below example.
CancellationTokenSource src = new CancellationTokenSource();
CancellationToken ct = src.Token;
Task t = Task.Run(async () =>
{
while(true){
ct.ThrowIfCancellationRequested();
await Task.Delay(new TimeSpan(0,30,0), ct);
await FooTask();
}
}, ct);
// Do some other stuff while your task runs
// Cancel Your Task, OR
ct.Cancel();
// Wait for your task to finish
try
{
t.Wait();
}
catch (AggregateException e)
{
// Handle the exception
}

Why doesn't it work to use ContinueWith to run task sequentially?

My goal was to start "Task2" after "Task1". At first I wrote code like "Code1" below, but it did not work (Task2 started before Task1 was finished). So I searched Stackoverflow and modified my code like "Code2" below as the existing answer suggested. I wonder why "Code1" did not work.
Code1
static void Main(string[] args)
{
var p = new Program();
p.Test2();
Console.ReadKey();
}
void Test2()
{
Task.Factory.StartNew(async () =>
{
await Task1();
}).ContinueWith((t) => {
Task2();
});
}
async Task Task1()
{
Debug.WriteLine("Task 1 starting....");
await LongTask();
Debug.WriteLine("Task 1 done");
}
Task LongTask()
{
return Task.Factory.StartNew(() =>
{
Thread.Sleep(3000);
});
}
void Task2()
{
Debug.WriteLine("Task 2");
}
Code2
Task.Factory.StartNew(async () =>
{
await Task1();
Task2();
}).ContinueWith((t) => {
//Task2();
});
Because when you are running task like Task.Factory.StartNew(async () => ... it returns Task<Task> (task of task). And first task terminates without waiting for the inner Task.
For preventing this situation, you can use Unwrap method:
Task.Factory.StartNew(async () =>
{
await Task1();
})
.Unwrap()
.ContinueWith((t) => {
Task2();
});
That StartNew will return Task<Task>, and it seems you want to execute continuation after inner task completion. That's why we need Unwrap.
It “unwraps” the inner task that’s returned as the result of the outer task. Calling Unwrap on a Task gives you back a new Task (which we often refer to as a proxy) which represents the eventual completion of the inner task. And then, we are adding continuation to the inner task.
But, as Task.Run will do that unwrapping automatically you can use Task.Run in that case:
Task.Run(async () =>
{
await Task1();
})
.ContinueWith((t) => {
Task2();
});
And that can be simplified to:
Task.Run(async () =>
{
await Task1();
Task2();
});
Detailed information about diferences between Task.Run and Task.Factory.StartNew:
Read more here from Stephen Toub who is an engineer in the .Net team. The reason of decision in case of Task.Run:
Because we expect it to be so common for folks to want to offload work
to the ThreadPool, and for that work to use async/await, we decided to
build this unwrapping functionality into Task.Run.
By the way, as Stephen recommended just try to use Task.Run in most cases, but this in no way obsoletes Task.Factory.StartNew, there is still some places in which Task.Factory.StartNew must be used:
Task.Factory.StartNew still has many important (albeit more advanced)
uses. You get to control TaskCreationOptions for how the task
behaves. You get to control the scheduler for where the task should
be queued to and run. You get to use overloads that accept object
state, which for performance-sensitive code paths can be used to avoid
closures and the corresponding allocations. For the simple cases,
though, Task.Run is your friend.
Task.Factory.StartNew don't understand async lambdas. For Task.Factory.StartNew your lambda is just function returning Task. It doesn't automatically await that task. Also, note that using Task.Factory.StarNew and ContinueWith is discouraged in modern C# as it hard to use correctly (please read, "StartNew is Dangerous" by Stephen Cleary). You should use Task.Factory.StarNew or ContinueWith only if you can't do without them.
Instead, you can just use async/await one more time:
async Task Test2()
{
await Task1();
Task2();
}
or Task.Run:
async Task Test2()
{
return Task.Run(await () =>
{
await Task1();
Task2();
});
}
The second approach might be convenient if you want to make sure that your asynchronous Task1() is started on background thread.

Async/Await action within Task.Run()

Task.Run(()=>{}) puts the action delegate into the queue and returns the task .
Is there any benefit of having async/await within the Task.Run()?
I understand that Task.Run() is required since if we want to use await directly, then the calling method will need to be made Async and will affect the calling places.
Here is the sample code which has async await within Task.Run(). The full sample is provided here: Create pre-computed tasks.
Task.Run(async () => { await new WebClient().DownloadStringTaskAsync("");});
Alternatively this could have been done:
Task.Run(() => new WebClient().DownloadStringTaskAsync("").Result;);
Since both, Task.Run() and Await will queue the work and will be picked by the thread pool, could the async/await within the Task.Run() be a bit redundant?
Is there any benefit of having async/await within the Task.Run() ?
Yes. Task.Run runs some action on a thread-pool thread. If such action does some IO work and asynchronously waits for the IO operation to complete via await, then this thread-pool thread can be used by the system for other work while the IO operation is still running.
Example:
Task.Run( async () =>
{
DoSomeCPUIntensiveWork();
// While asynchronously waiting for this to complete,
// the thread is given back to the thread-pool
var io_result = await DoSomeIOOperation();
DoSomeOtherCPUIntensiveWork(io_result);
});
Is there any benefit of having async/await within the Task.Run()
An async method returns to the caller as soon as the first await is hit (that operates on a non-completed task). So if that first execution "streak" of an async method takes a long time Task.Run will alter behavior: It will cause the method to immediately return and execute that first "streak" on the thread-pool.
This is useful in UI scenarios because that way you can make 100% sure that you are not blocking the UI. Example: HttpWebRequestdoes DNS resolution synchronously even when you use one of the async methods (this is basically a library bug/design error). This can pause the UI thread. So you can use Task.Run to be 100% sure that the UI is never blocked for longer than a few microseconds.
So back to the original question: Why await inside a Task.Run body? For the same reason you normally await: To unblock the thread.
In the example that you linked the main thread is being blocked until the asynchronous operation is done. It's being blocked by calling Wait() (which by the way is generally a bad idea).
Let's have a look at the return from the DownloadStringAsync in the linked sample:
return Task.Run(async () =>
{
content = await new WebClient().DownloadStringTaskAsync(address);
cachedDownloads.TryAdd(address, content);
return content;
});
Why would you wrap this in a Task? Think about your options for a second. If you don't want to wrap this in a Task, how would you make sure the method returns a Task<string> and still have it work? You'd mark the method as async of course! However, if you mark your method as async and you call Wait on it, you'll most likely end up with a deadlock, since the main thread is waiting for the work to finish, and your blocking the main thread so it can't let you know it's done.
When marking a method as async, the state machine will run on the calling thread, in your example however, the state machine runs on a separate thread, meaning there is little to no work being done on the main thread.
Calling Async from Non-Async Methods
We do some stuff like that when we are trying to call an async method inside of a non-async method. Especially if the async method is a known quantity. We use more of a TaskFactory though ... fits a pattern, makes it easier to debug, makes sure everyone takes the same approach (and -- gives us one throat to choke if async-->sync starts acting buggy).
So, Your Example
Imagine, in your example, that you have a non-async function. And, within that function, you need to call await webClient.DoSomethingAsync(). You can't call await inside of a function that's not async -- the compiler won't let you.
Option 1: Zombie Infestation
Your first option is to crawl all the way back up your call stack, marking every da*n method along the way as async and adding awaits everywhere. Everywhere. Like, everywhere. Then -- since all those methods are now async, you need to make the methods that reference them all async.
This, btw, is probably the approach many of the SO enthusiasts are going to advocate. Because, "blocking a thread is a bad idea."
So. Yeah. This "let async be async" approach means your little library routine to get a json object just reached out and touched 80% of the code. Who's going to call the CTO and let him know?
Option 2: Just Go with the One Zombie
OR, you can encapsulate your async inside of some function like yours...
return Task.Run(async () => {
content = await new WebClient().DoSomethingAsync();
cachedDownloads.TryAdd(address, content);
return content;
});
Presto... the zombie infestation has been contained to a single section of code. I'll leave it to the bit-mechanics to argue over how/why that gets executed at the CPU-level. I don't really care. I care that nobody has to explain to the CTO why the entire library should now be 100% async (or something like that).
Confirmed, wrapping await with Task.Run use 2 threads instead of one.
Task.Run(async () => { //thread #1
await new WebClient().DownloadStringTaskAsync(""); //thread #2
});
Say you have four calls wrapped like this, it will use 4 x 2 = 8 threads.
It would be better to just call these with simple await instead. For example:
Task<byte[]> t1 = new WebClient().DownloadStringTaskAsync("");
Task<byte[]> t2 = new WebClient().DownloadStringTaskAsync("");
byte[] t1Result = await t1;
byte[] t2Result = await t2;
Here is the proof that wrapped Task.Run are using extra threads. (Not using WebClient to prove the point)
private static async Task wrapped()
{
List<Task> tasks = new List<Task>();
tasks.AddRange(new []
{
Task.Run(async() => await new MyThread().RunMe()),
Task.Run(async() => await new MyThread().RunMe()),
Task.Run(async() => await new MyThread().RunMe()),
Task.Run(async() => await new MyThread().RunMe()),
});
Thread.Sleep(1000);
int number = Process.GetCurrentProcess().Threads.Count;
Console.WriteLine($"While running thread count: {number}");
await Task.WhenAll(tasks);
}
Unwrapped
private static async Task unwrapped()
{
List<Task> tasks = new List<Task>();
Task<int> t1 = new MyThread().RunMe();
Task<int> t2 = new MyThread().RunMe();
Task<int> t3 = new MyThread().RunMe();
Task<int> t4 = new MyThread().RunMe();
tasks.AddRange(new[] {t1, t2, t3, t4});
Thread.Sleep(1000);
int number = Process.GetCurrentProcess().Threads.Count;
Console.WriteLine($"While running thread count: {number}");
int i1 = await t1;
int i2 = await t2;
int i3 = await t3;
int i4 = await t4;
}
Full POC code here
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncThreadDemo
{
class Program
{
static async Task Main(string[] args)
{
int number = Process.GetCurrentProcess().Threads.Count;
Console.WriteLine($"Init thread count: {number}");
//await wrapped();
await unwrapped();
number = Process.GetCurrentProcess().Threads.Count;
Console.WriteLine($"Done thread count: {number}");
Console.ReadLine();
}
private static async Task wrapped()
{
List<Task> tasks = new List<Task>();
tasks.AddRange(new []
{
Task.Run(async() => await new MyThread().RunMe()),
Task.Run(async() => await new MyThread().RunMe()),
Task.Run(async() => await new MyThread().RunMe()),
Task.Run(async() => await new MyThread().RunMe()),
});
Thread.Sleep(1000);
int number = Process.GetCurrentProcess().Threads.Count;
Console.WriteLine($"While running thread count: {number}");
await Task.WhenAll(tasks);
}
private static async Task unwrapped()
{
List<Task> tasks = new List<Task>();
Task<int> t1 = new MyThread().RunMe();
Task<int> t2 = new MyThread().RunMe();
Task<int> t3 = new MyThread().RunMe();
Task<int> t4 = new MyThread().RunMe();
tasks.AddRange(new[] {t1, t2, t3, t4});
Thread.Sleep(1000);
int number = Process.GetCurrentProcess().Threads.Count;
Console.WriteLine($"While running thread count: {number}");
int i1 = await t1;
int i2 = await t2;
int i3 = await t3;
int i4 = await t4;
}
}
public class MyThread
{
public static int _counter;
public async Task<int> RunMe()
{
await Task.Run(() =>
{
for (int i = 0; i < 2; ++i)
{
Thread.Sleep(1000);
Console.WriteLine($"T{Thread.CurrentThread.ManagedThreadId} {i}");
}
Console.WriteLine($"T{Thread.CurrentThread.ManagedThreadId} done");
});
return _counter++;
}
}
}

How to call async methods

Imagine there is a method
async static System.Threading.Tasks.Task Do()
{
//do sth
await Task.Delay(10000);
}
now , when I call the method with
Do();
Does it make a new thread ? or I have to create a thread as below
Task.Factory.StartNew(() => Do());
Do doesn't create a thread.
The part before the await runs on the calling thread and there's no thread at all during the delay. Task.Delay uses a timer internally which doesn't hold up a thread throughout the operation.
When the delay completes a thread from the ThreadPool is used to continue executing the method.
About Task.Factory.StartNew, why would you want to create a thread? If you need to offload a CPU intensive method to the thread pool then it's fine (although Task.Run is preferable) but if you don't then simply call Do and await the result:
await Do();
If you insist on creating a new thread for Do you need to use TaskCreationOptions.LongRunning:
Task.Factory.StartNew(() => Do(), TaskCreationOptions.LongRunning);
But since Do is an async method that releases the thread when it reaches the first await this doesn't make any sense as I've explained on my blog: LongRunning Is Useless For Task.Run With async-await
All my case is this :
public void Start(Action action)
{
Token = CancellationToken.None;
IsRunning = true;
Task.Factory.StartNew(() => Do(action), TaskCreationOptions.LongRunning);
}
async Task Do(Action action)
{
while (IsRunning)
{
action();
await Task.Delay(Interval, Token);
}
}
then I call Start() with five different actions with different intervals.
Is this Correct to use ?

Threading: Application Freezes after using Thread.Join()

I understand that the .Join() causes the threads to pause and wait till a thread finishes its work but how can I avoid the UI from getting frozen? This is what my codes look like"
Thread dataThread = new Thread(()=> data = getData(id));
dataThread.Start();
dataThread.Join();
Thread storingThread = new Thread(()=> storeData(data));
storingThread.Start();
I need to have the Join since the first thread returns an object containing data that needs to be stored through the second thread. But this causes a UI freeze. How can I implement these in maybe a Background thread? What do yall think I should change?
If you are using .Net framework >= 4.5 you can use Tasks
await Task.Run(() => data = getData(id));
await Task.Run(() => storeData(data));
Or in one command
await Task.Run(() => storeData(getData(id)));
If you don't have to wait till it's finished you can also do:
Task.Run(() => storeData(getData(id)));
It seems you don't need two threads:
Thread dataThread = new Thread(() => storeData(getData(id)));
dataThread.Start();
Note, that Task is preferable to Thread. Also, you probably should make use of await.
The answer has already been given. Just as an extra, I give mine.
You can also use ContinueWith like this:
Task<string>.Factory.StartNew(() => "Hey!").ContinueWith(t => Console.WriteLine(t.Result));
Put the whole work into one thread so the UI doesn't stop:
ThreadPool.QueueUserWorkItem( () => storeData(getData(id)));
Or for .Net 4
Task.Factory.StartNew(() => storeData(getData(id)));
Use the async / await keywords. Small example code:
private async void Method()
{
var result = await ExecuteAsync();
// result == true
}
private async Task<bool> ExecuteAsync()
{
//run long running action
return true;
}
In .net 4.0 you need to install Microsoft.Bcl.Async to use this feature.
A good introduction in this feature can be read on http://blog.stephencleary.com/2012/02/async-and-await.html

Categories