Call async method after another async method is finished in C# - c#

I want to call step2 method after step 1 is finished. With this code below the methods step 1 and step 2 are executing in parallel. And of course I they need to be asynchronous so they won't block step 3 from executing.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace test
{
internal class Program
{
static void Main(string[] args)
{
async void step1()
{
await Task.Run(() =>
{
Thread.Sleep(2000);
Console.WriteLine("step 1");
});
}
async void step2()
{
await Task.Run(() =>
{
Thread.Sleep(5000);
Console.WriteLine("step 2");
});
}
void step3()
{
Console.WriteLine("step 3");
}
step1();
step2();
step3();
// the code below is not working but just and idea
// what I want to make. If it at all posible
// step1().step2()
// step3()
Console.ReadLine();
}
}
}
Any help would be greatly appreciated. Keep in mind I am beginner in C#!
Edit:
I know that I can get the end result even with this code.
void step1()
{
Thread.Sleep(2000);
Console.WriteLine("step 1");
}
void step2()
{
Thread.Sleep(5000);
Console.WriteLine("step 2");
}
void step3()
{
Console.WriteLine("step 3");
}
step3();
step1();
step2();
even without async/await at all.
The point of this question is to make small proof of concept application where even though the code is set up like this:
step1();
step2();
step3();
where step3() is set last will execute first because has no delay and also step2() will have to wait for step1() to finish.
Is this at all possible with async/await in C#. I think this can be done with promises in javascript.

There may be a misunderstanding about how asynchronous methods work. All async methods start running synchronously, just like any other method. The magic happens when await acts on a Task that is incomplete. At that point, the method returns a new incomplete Task to the calling method (or returns nothing if it's void, which is why you should avoid async void).
So if you call step1() first, then step1() will start executing first - there is no way around that. But when step1() hits await Task.Run(...) then it returns and the Main method continues executing. At that point, you can decide what to do. Do you want to wait until step1() completes or go do something else?
Here is what the code would look like if you want:
step1() to start executing first.
step2() to only start after step1() completes.
step3() executes as soon as possible after step1() starts, but without waiting for step1() to complete.
static async Task Main(string[] args)
{
async Task step1()
{
Console.WriteLine("step 1 starting");
await Task.Run(() =>
{
Thread.Sleep(2000);
Console.WriteLine("step 1 done");
});
}
async Task step2()
{
Console.WriteLine("step 2 starting");
await Task.Run(() =>
{
Thread.Sleep(5000);
Console.WriteLine("step 2 done");
});
}
void step3()
{
Console.WriteLine("step 3");
}
var step1task = step1();
step3();
await step1task;
await step2();
Console.ReadLine();
}
The output is:
step 1 starting
step 3
step 1 done
step 2 starting
step 2 done
If you want step3() to execute before step1() even starts executing, then you need to call step3() first - no way around it.

If you change your Main method (as well as step1 and step2) to async Task instead of void (or async void), you'll be able to await your methods.
static async Task Main(string[] args)
{
async Task step1()
{
await Task.Run(() =>
{
Thread.Sleep(2000);
Console.WriteLine("step 1");
});
}
async Task step2()
{
await Task.Run(() =>
{
Thread.Sleep(5000);
Console.WriteLine("step 2");
});
}
void step3()
{
Console.WriteLine("step 3");
}
step3(); // You can put step3 here if you want it to run before step1 and step2.
await step1();
await step2();
Console.ReadLine();
}
I suggest you check this Microsoft article to get a better understanding of async Task vs async void.

If the constraints are
step2 should start when step1 ends
step1 and step2 should not block step3
Calling code must be (e.g. no ContinueWith)
step1();
step2();
step3();
Then the answer is this is not possible.
Unless you have control of the code inside the steps, and do thread signalling to prevent step2 to start before step1 ends. Read about ManualResetEvent.
static void Main(string[] args)
{
var mre = new ManualResetEvent(false);
void step1()
{
Task.Run(() =>
{
Thread.Sleep(1000);
Console.WriteLine("step 1");
mre.Set();
});
}
void step2()
{
Task.Run(() =>
{
mre.WaitOne();
Console.WriteLine("step 2");
});
}
void step3()
{
Console.WriteLine("step 3");
}
step1();
step2();
step3();
Console.ReadLine();
}

Drop the async, it is not meaning what you think. Use ContinueWith
Task step1()
{
return Task.Run(() =>
{
Thread.Sleep(2000);
Console.WriteLine("step 1");
});
}
Task step2()
{
return Task.Run(() =>
{
Thread.Sleep(5000);
Console.WriteLine("step 2");
});
}
void step3()
{
Console.WriteLine("step 3");
}
var task = step1()
.ContinueWith(x => step2());
step3();
task.Wait();

Related

Does await pass control to the caller? Or does await suspend the thread? Why does the top level call need an await?

1 thread is running the program.
It prints Main Method Started....
Then prints Some Method Started....
Then I was expecting that await Task.Delay will release the thread into the pool until the Task delay completes. But that seems to happen only if the call to SomeMethod would have been like this: await SomeMethod();
In the current example it prints Main Method End.... Does await pass control to the caller? Or does await suspend the thread?
using System;
using System.Threading.Tasks;
namespace AsynchronousProgramming
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main Method Started......");
SomeMethod();
Console.WriteLine("Main Method End");
Console.ReadKey();
}
public async static void SomeMethod()
{
Console.WriteLine("Some Method Started......");
//Thread.Sleep(TimeSpan.FromSeconds(10));
await Task.Delay(TimeSpan.FromSeconds(10));
Console.WriteLine("\n");
Console.WriteLine("Some Method End");
}
}
}

Timeout for long running 3rd library method

I want to add ability to cancel long running external method (in code below is it LongOperation method from SomeExternalClass class), so I wrap this method into task and add custom task extension for handle timeout.
TimeoutException is successful throwed after specific period of time, but external method is not canceled. How I can cancel LongOperation?
class Program
{
private static CancellationTokenSource cancellationTokenSource;
static async Task Main(string[] args)
{
cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.Token.ThrowIfCancellationRequested();
try
{
await SearchTask().WithTimeout(TimeSpan.FromSeconds(2));
}
catch (TimeoutException)
{
Console.WriteLine("Timeout");
cancellationTokenSource.Cancel();
}
Console.WriteLine("Program end");
Console.ReadKey();
}
private static Task SearchTask()
{
return Task.Run(() =>
{
Console.WriteLine("Start task");
SomeExternalClass.LongOperation();
Console.WriteLine("End task");
}, cancellationTokenSource.Token);
}
}
public static class SomeExternalClass
{
// this is simulation of long running 3rd party method
public static void LongOperation()
{
Console.WriteLine("Start LongOperation");
Thread.Sleep(10000);
Console.WriteLine("End LongOperation");
}
}
public static class TaskExtension
{
public static async Task WithTimeout(this Task task, TimeSpan timeout)
{
if (task == await Task.WhenAny(task, Task.Delay(timeout)))
{
await task;
}
throw new TimeoutException();
}
}
The output is:
Start task
Start LongOperation
Timeout
Program end
End LongOperation
End task

Asynchronous method in button click [duplicate]

I'm starting to learn about async / await in C# 5.0, and I don't understand it at all. I don't understand how it can be used for parallelism. I've tried the following very basic program:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Task task1 = Task1();
Task task2 = Task2();
Task.WaitAll(task1, task2);
Debug.WriteLine("Finished main method");
}
public static async Task Task1()
{
await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
Debug.WriteLine("Finished Task2");
}
}
}
This program just blocks on the call to Task.WaitAll() and never finishes, but I am not understanding why. I'm sure I'm just missing something simple or just don't have the right mental model of this, and none of the blogs or MSDN articles that are out there are helping.
I recommend you start out with my intro to async/await and follow-up with the official Microsoft documentation on TAP.
As I mention in my intro blog post, there are several Task members that are holdovers from the TPL and have no use in pure async code. new Task and Task.Start should be replaced with Task.Run (or TaskFactory.StartNew). Similarly, Thread.Sleep should be replaced with Task.Delay.
Finally, I recommend that you do not use Task.WaitAll; your Console app should just Wait on a single Task which uses Task.WhenAll. With all these changes, your code would look like:
class Program
{
static void Main(string[] args)
{
MainAsync().Wait();
}
public static async Task MainAsync()
{
Task task1 = Task1();
Task task2 = Task2();
await Task.WhenAll(task1, task2);
Debug.WriteLine("Finished main method");
}
public static async Task Task1()
{
await Task.Delay(5000);
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Delay(10000);
Debug.WriteLine("Finished Task2");
}
}
Understand C# Task, async and await
C# Task
Task class is an asynchronous task wrapper. Thread.Sleep(1000) can stop a thread running for 1 second. While Task.Delay(1000) won't stop the current work. See code:
public static void Main(string[] args){
TaskTest();
}
private static void TaskTest(){
Task.Delay(5000);
System.Console.WriteLine("task done");
}
When running," task done" will show up immediately. So I can assume that every method from Task should be asynchronous. If I replace TaskTest () with Task.Run(() =>TaskTest()) task done won't show up at all until I append a Console.ReadLine(); after the Run method.
Internally, Task class represent a thread state In a State Machine. Every state in state machine have several states such as Start, Delay, Cancel, and Stop.
async and await
Now, you may wondering if all Task is asynchronous, what is the purpose of Task.Delay ? next, let's really delay the running thread by using async and await
public static void Main(string[] args){
TaskTest();
System.Console.WriteLine("main thread is not blocked");
Console.ReadLine();
}
private static async void TaskTest(){
await Task.Delay(5000);
System.Console.WriteLine("task done");
}
async tell caller, I am an asynchronous method, don't wait for me. await inside the TaskTest() ask for waiting for the asynchronous task. Now, after running, program will wait 5 seconds to show the task done text.
Cancel a Task
Since Task is a state machine, there must be a way to cancel the task while task is in running.
static CancellationTokenSource tokenSource = new CancellationTokenSource();
public static void Main(string[] args){
TaskTest();
System.Console.WriteLine("main thread is not blocked");
var input=Console.ReadLine();
if(input=="stop"){
tokenSource.Cancel();
System.Console.WriteLine("task stopped");
}
Console.ReadLine();
}
private static async void TaskTest(){
try{
await Task.Delay(5000,tokenSource.Token);
}catch(TaskCanceledException e){
//cancel task will throw out a exception, just catch it, do nothing.
}
System.Console.WriteLine("task done");
}
Now, when the program is in running, you can input "stop" to cancel the Delay task.
Your tasks never finish because they never start running.
I would Task.Factory.StartNew to create a task and start it.
public static async Task Task1()
{
await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
Debug.WriteLine("Finished Task2");
}
As a side note, if you're really just trying to pause in a async method, there's no need to block an entire thread, just use Task.Delay
public static async Task Task1()
{
await Task.Delay(TimeSpan.FromSeconds(5));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Delay(TimeSpan.FromSeconds(10));
Debug.WriteLine("Finished Task2");
}
Async and await are markers which mark code positions from where control should resume after a task (thread) completes.
Here's a detail youtube video which explains the concept in a demonstrative manner http://www.youtube.com/watch?v=V2sMXJnDEjM
If you want you can also read this coodeproject article which explains the same in a more visual manner.
http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features#Feature1:-“Async”and“Await”(Codemarkers)
static void Main(string[] args)
{
if (Thread.CurrentThread.Name == null)
Thread.CurrentThread.Name = "Main";
Console.WriteLine(Thread.CurrentThread.Name + "1");
TaskTest();
Console.WriteLine(Thread.CurrentThread.Name + "2");
Console.ReadLine();
}
private async static void TaskTest()
{
Console.WriteLine(Thread.CurrentThread.Name + "3");
await Task.Delay(2000);
if (Thread.CurrentThread.Name == null)
Thread.CurrentThread.Name = "FirstTask";
Console.WriteLine(Thread.CurrentThread.Name + "4");
await Task.Delay(2000);
if (Thread.CurrentThread.Name == null)
Thread.CurrentThread.Name = "SecondTask";
Console.WriteLine(Thread.CurrentThread.Name + "5");
}
If you run this program you will see that await will use different thread. Output:
Main1
Main3
Main2
FirstTask4 // 2 seconds delay
SecondTask5 // 4 seconds delay
But if we remove both await keywords, you will learn that async alone doesn't do much. Output:
Main1
Main3
Main4
Main5
Main2

Xamarin - trying to create a equivalent of JS setInterval using Thread

I was creating a puzzle with a bit of information in different sources to create this...
System.Threading.Thread th;
th = new System.Threading.Thread(new System.Threading.ThreadStart(() =>
{
InvokeOnMainThread(() =>
{
lbMemFree.Text = "memory free: " + NSProcessInfo.ProcessInfo.PhysicalMemory; // this works!
});
}));
th.Start();
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
th.Sleep(500); // delay execution for 500 ms
// more code
});
The idea is to create something that update the label times in time. In this scenario: 500ms.
But the th.Sleep(500) don't allow the app to compile. It's says: Error CS0176: Static member System.Threading.Thread.Sleep(int) cannot be accessed with an instance reference, qualify it with a type name instead (CS0176).
You can use async await for this.
Interval
public class Interval
{
public static async Task SetIntervalAsync(Action action, int delay, CancellationToken token)
{
try
{
while (!token.IsCancellationRequested)
{
await Task.Delay(delay, token);
action();
}
}
catch(TaskCanceledException) { }
}
}
usage (e.g. Console Application for demo)
class Program
{
static void Main(string[] args)
{
var cts = new CancellationTokenSource();
Interval.SetIntervalAsync(DoSomething, 1000, cts.Token);
Console.ReadKey(); // cancel after first key press.
cts.Cancel();
Console.ReadKey();
}
public static void DoSomething()
{
Console.WriteLine("Hello World");
}
}
Use the CancellationTokenSource to cancel the execution of the interval.

Can I use async / await to simulate a background worker?

I'm trying to avoid having to chain a bunch of BackgroundWorkers together. I'm doing something that requires me to wait for the UI to update before continuing execution. Obviously, I can't use Sleep, as this blocks the UI thread from updating and defeats the purpose. I found the code below which I thought was the answer, but it appears the task.Wait(); line is still blocking the UI thread.
static void Main(string[] args)
{
var task = Task.Run(() => DoSomething());
task.Wait();
// once the task completes, now do more
}
static void DoSomething()
{
// something here that is looking for the UI to change
}
I also tried the following, which did the same thing:
static void Main(string[] args)
{
var task = Task.Run(() => DoSomethingAsync());
task.Wait();
// once the task completes, now do more
}
private async Task DoSomethingAsync()
{
// something here that is looking for the UI to change
}
Is it possible to do what I want, and if so, what am I doing wrong?
You need to await the task instead of blocking on it. You can do that inside an async method.
Now, Main can't be async but an event handler can be (which I guess is where you actually use that code):
public async void EventHandler(object sender, EventArgs e)
{
await Task.Run(() => DoSomething()); // wait asynchronously
// continue on the UI thread
}
Note that it's async void which should only be used on event handlers. All other async methods should return a task.
Using Task.Run means your using a ThreadPool thread. To really wait asynchronously for the UI to "do something" you should use TaskCompletionSource. You create it and await it's Task property and you complete that task when the UI changed:
public async void EventHandler(object sender, EventArgs e)
{
_tcs = new TaskCompletionSource<bool>();
await _tcs.Task;
}
public void UIChanged(object sender, EventArgs e)
{
_tcs.SetResult(false);
}

Categories

Resources