Understanding Task based asynchronous pattern C# - c#

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.
}

Related

Async function not launching asynchronously

I still meet issues calling async functions.
In that code, I execute generateAllIfcs(dataFolder), then I would like to execute already addToExistingContract() or this.importNewContract() depending on contexte.SourceContract.
But this line is not reached until generateAllIfcs(dataFolder) is finished.
private async void Import(object sender, RoutedEventArgs e)
{
Task<bool> successGenerateIfc = this.generateAllIfcs(dataFolder);
Task<bool> successAddContractToVsteel = contexte.SourceContract != null ?
this.addToExistingContract() : this.importNewContract();
await Task.WhenAll(successGenerateIfc, successAddContractToVsteel);
}
private async Task<bool> generateAllIfcs(string dataFolder)
{
try
{
var progressIndicator4 = new Progress<int>(contexte.ReportProgress4);
if (contexte.SourceContract != null)
{
int total4 = await contexte.NewModel.ExportNewIfcContract(
contexte.SourceContract, progressIndicator4, 0, 100,
contexte.SelectedConfigImportIFC, true,dataFolder);
}
else
{
int total4 = await contexte.NewModel.ExportNewIfcContract(null,
progressIndicator4, 0, 100, contexte.SelectedConfigImportIFC,
true, dataFolder);
}
return true;
}
catch
{
return false;
}
}
public async Task<int> ExportNewIfcContract(Contract existingContract,
IProgress<int> progress, int startProgress, int endProgress,
ConfigImportIFC config, bool generateIfcAssAndRep, string dataFolder)
{
int retour = await this.exportNewIfcContract(existingContract, progress,
startProgress, endProgress,config, generateIfcAssAndRep, dataFolder);
return retour;
}
private async Task<int> exportNewIfcContract(Contract existingContract,
IProgress<int> progress, int startProgress, int endProgress,
ConfigImportIFC config, bool generateIfcAssAndRep, string dataFolder)
{
//some other calls to async functions
}
"async function not launching asynchronously" - yes, that's normal; async isn't about how things launch, it is about how they complete (or at least, continue); async doesn't mean "parallel", "concurrent", etc - and has only tangential relationship to threading; an async method runs synchronously until the first incomplete await, i.e. where the thing being awaited did not itself finish synchronously. Only for an incomplete await does the async engine unroll itself and register a continuation. I don't see anything inherently truly async in your code, although to be fair: I can't see exportNewIfcContract.
If you want concurrency, consider Task.Run etc to invoke a second execution flow. Or alternatively, consider adding:
await Task.Yield();
at the top of generateAllIfcs (the method that you intend to run concurrently); Task.Yield() always returns in an incomplete state, pushing the rest of the work as a continuation onto the thread-pool.

C# wait for a function that returns void to finish a System.NET.WebClient.DownloadFileAsync() while still keeping an active WinForms UI [duplicate]

How can I wait for a void async method to finish its job?
for example, I have a function like below:
async void LoadBlahBlah()
{
await blah();
...
}
now I want to make sure that everything has been loaded before continuing somewhere else.
Best practice is to mark function async void only if it is fire and forget method, if you want to await on, you should mark it as async Task.
In case if you still want to await, then wrap it like so await Task.Run(() => blah())
If you can change the signature of your function to async Task then you can use the code presented here
The best solution is to use async Task. You should avoid async void for several reasons, one of which is composability.
If the method cannot be made to return Task (e.g., it's an event handler), then you can use SemaphoreSlim to have the method signal when it is about to exit. Consider doing this in a finally block.
You don't really need to do anything manually, await keyword pauses the function execution until blah() returns.
private async void SomeFunction()
{
var x = await LoadBlahBlah(); <- Function is not paused
//rest of the code get's executed even if LoadBlahBlah() is still executing
}
private async Task<T> LoadBlahBlah()
{
await DoStuff(); <- function is paused
await DoMoreStuff();
}
T is type of object blah() returns
You can't really await a void function so LoadBlahBlah() cannot be void
I know this is an old question, but this is still a problem I keep walking into, and yet there is still no clear solution to do this correctly when using async/await in an async void signature method.
However, I noticed that .Wait() is working properly inside the void method.
and since async void and void have the same signature, you might need to do the following.
void LoadBlahBlah()
{
blah().Wait(); //this blocks
}
Confusingly enough async/await does not block on the next code.
async void LoadBlahBlah()
{
await blah(); //this does not block
}
When you decompile your code, my guess is that async void creates an internal Task (just like async Task), but since the signature does not support to return that internal Tasks
this means that internally the async void method will still be able to "await" internally async methods. but externally unable to know when the internal Task is complete.
So my conclusion is that async void is working as intended, and if you need feedback from the internal Task, then you need to use the async Task signature instead.
hopefully my rambling makes sense to anybody also looking for answers.
Edit:
I made some example code and decompiled it to see what is actually going on.
static async void Test()
{
await Task.Delay(5000);
}
static async Task TestAsync()
{
await Task.Delay(5000);
}
Turns into (edit: I know that the body code is not here but in the statemachines, but the statemachines was basically identical, so I didn't bother adding them)
private static void Test()
{
<Test>d__1 stateMachine = new <Test>d__1();
stateMachine.<>t__builder = AsyncVoidMethodBuilder.Create();
stateMachine.<>1__state = -1;
AsyncVoidMethodBuilder <>t__builder = stateMachine.<>t__builder;
<>t__builder.Start(ref stateMachine);
}
private static Task TestAsync()
{
<TestAsync>d__2 stateMachine = new <TestAsync>d__2();
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>1__state = -1;
AsyncTaskMethodBuilder <>t__builder = stateMachine.<>t__builder;
<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
neither AsyncVoidMethodBuilder or AsyncTaskMethodBuilder actually have any code in the Start method that would hint of them to block, and would always run asynchronously after they are started.
meaning without the returning Task, there would be no way to check if it is complete.
as expected, it only starts the Task running async, and then it continues in the code.
and the async Task, first it starts the Task, and then it returns it.
so I guess my answer would be to never use async void, if you need to know when the task is done, that is what async Task is for.
do a AutoResetEvent, call the function then wait on AutoResetEvent and then set it inside async void when you know it is done.
You can also wait on a Task that returns from your void async
You can simply change the return type to Task and call await Task.CompletedTask at the end of the function, e.g:
async Task MyFunction() {
await AnotherFunction();
await Task.CompletedTask;
}
I find this simpler than wrapping the whole function body in a call to Task.Run(() => { ... });.
I've read all the solutions of the thread and it's really complicated... The easiest solution is to return something like a bool:
async bool LoadBlahBlah()
{
await blah();
return true;
}
It's not mandatory to store or chekc the return value. You can juste do:
await LoadBlahBlah();
... and you can return false if something goes wrong.

Confusion on async and await logic in c#?

i have a great confusion while working with the async and await.
My logic is simple, i have a method which will cause a delay of 15 seconds, like this
public static Task<int> delay(int num)
{
Task.Delay(15000);
return Task.FromResult(num);
}
now i am calling this method like this
public static async void delayAsync(int num)
{
Console.WriteLine(await delay(num)+"time :"+DateTime.Now);
}
static void Main(string[] args)
{
var details = new details();
Console.WriteLine("## start ##");
for (var i = 0; i < 5; i++)
{
Console.WriteLine("counter: "+i);
delayAsync(i);
}
Console.WriteLine("## finished ##");
Console.Read();
}
my desired output is to get the number one by one after the delay of 15 seconds, but i am getting the results all at once without any pause. am i missing something.
I have gone through this blog and couldnt understand a thing
Here are the steps that you need to achieve this:
Await Task.Delay and return num instead of Task.
public static async Task<int> delay(int num)
{
await Task.Delay(15000);
return num;
}
Make your delayAsync method return Task.
public static async Task delayAsync(int num)
{
Console.WriteLine(await delay(num) + "time :" + DateTime.Now);
}
Wait for the result of the delayAsync in you Main method.
public static void Main(string[] args)
{
Console.WriteLine("## start ##");
for (var i = 0; i < 5; i++)
{
Console.WriteLine("counter: " + i);
delayAsync(i).Wait();
}
Console.WriteLine("## finished ##");
Console.Read();
}
You are not awaiting the Task.Delay
public static async Task<int> delay(int num){
await Task.Delay(15000);
return num;
}
Note that the signature of the method needs to include async. Additionally since you are now using await inside the method, you don't need to explicitly create a Task for the return statement.
Additionally you have to await the delayAsync call in your Main method (note that you cannot make Main async so you have to use a workaround like this: https://stackoverflow.com/a/9212343/868361
my desired output is to get the number one by one after the delay of 15 seconds
When you call an async method that you don't await then the compiler will start it and continue with the rest of the procedures. In your case with the rest of the loop. So the simple solution to get your desired output would be here:
Don't use async methods! Simply make it a serial processing.
To achieve that what you want using async you would have to wait in the loop for the delayAsync method. But this would make the asynchronous processing synchronous and you would end up again in the normal 1 thread serial processing, only having invested a lot of effort to end up from where you started.

Async all the way vs. Task.Run on a simple calculation method

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

Best asynchronous while method

I need to write some asynchronous code that essentially attempts to repeatedly talk to and initialise a database. Quite often the first attempt will fail hence the requirement for it to retry.
In days of old I would have used a pattern similar to:
void WaitForItToWork()
{
bool succeeded = false;
while (!succeeded)
{
// do work
succeeded = outcome; // if it worked, mark as succeeded, else retry
Threading.Thread.Sleep(1000); // arbitrary sleep
}
}
I realise a lot of changes have been made recently to .NET with regards to async patterns so my question really is this the best method to use or is it worth while exploring the async stuff and if so how do I implement this pattern in async?
Update
Just to clarify, I want to spawn this work asynchronously so that the method which spawns it does not have to wait for it to finish as it will be spawned in the constructor of a service so the constructor must return instantly.
You could refactor that fragment like this:
async Task<bool> WaitForItToWork()
{
bool succeeded = false;
while (!succeeded)
{
// do work
succeeded = outcome; // if it worked, make as succeeded, else retry
await Task.Delay(1000); // arbitrary delay
}
return succeeded;
}
Apparently, the only benefit it would give you is more efficient use of thread pool, because it doesn't always take a whole thread to make the delay happen.
Depending on how you obtain outcome, there may be much more efficient ways to get this job done using async/await. Often you may have something like GetOutcomeAsync() which would make a web service, database or socket call asynchronously in a natural way, so you'd just do var outcome = await GetOutcomeAsync().
It's important to take into account that WaitForItToWork will be split into parts by compiler and the part from await line will be continued asynchronously. Here's perhaps the best explanation on how it's done internally. The thing is, usually at some point of your code you'd need to synchronize on the result of the async task. E.g.:
private void Form1_Load(object sender, EventArgs e)
{
Task<bool> task = WaitForItToWork();
task.ContinueWith(_ => {
MessageBox.Show("WaitForItToWork done:" + task.Result.toString()); // true or false
}, TaskScheduler.FromCurrentSynchronizationContext());
}
You could have simply done this:
private async void Form1_Load(object sender, EventArgs e)
{
bool result = await WaitForItToWork();
MessageBox.Show("WaitForItToWork done:" + result.toString()); // true or false
}
That would however make Form1_Load an async method too.
[UPDATE]
Below is my attempt to to illustrate what async/await actually does in this case. I created two versions of the same logic, WaitForItToWorkAsync (using async/await) and WaitForItToWorkAsyncTap (using TAP pattern without async/await). The frist version is quite trivial, unlike the second one. Thus, while async/await is largely the compiler's syntactic sugar, it makes asynchronous code much easier to write and understand.
// fake outcome() method for testing
bool outcome() { return new Random().Next(0, 99) > 50; }
// with async/await
async Task<bool> WaitForItToWorkAsync()
{
var succeeded = false;
while (!succeeded)
{
succeeded = outcome(); // if it worked, make as succeeded, else retry
await Task.Delay(1000);
}
return succeeded;
}
// without async/await
Task<bool> WaitForItToWorkAsyncTap()
{
var context = TaskScheduler.FromCurrentSynchronizationContext();
var tcs = new TaskCompletionSource<bool>();
var succeeded = false;
Action closure = null;
closure = delegate
{
succeeded = outcome(); // if it worked, make as succeeded, else retry
Task.Delay(1000).ContinueWith(delegate
{
if (succeeded)
tcs.SetResult(succeeded);
else
closure();
}, context);
};
// start the task logic synchronously
// it could end synchronously too! (e.g, if we used 'Task.Delay(0)')
closure();
return tcs.Task;
}
// start both tasks and handle the completion of each asynchronously
private void StartWaitForItToWork()
{
WaitForItToWorkAsync().ContinueWith((t) =>
{
MessageBox.Show("WaitForItToWorkAsync complete: " + t.Result.ToString());
}, TaskScheduler.FromCurrentSynchronizationContext());
WaitForItToWorkAsyncTap().ContinueWith((t) =>
{
MessageBox.Show("WaitForItToWorkAsyncTap complete: " + t.Result.ToString());
}, TaskScheduler.FromCurrentSynchronizationContext());
}
// await for each tasks (StartWaitForItToWorkAsync itself is async)
private async Task StartWaitForItToWorkAsync()
{
bool result = await WaitForItToWorkAsync();
MessageBox.Show("WaitForItToWorkAsync complete: " + result.ToString());
result = await WaitForItToWorkAsyncTap();
MessageBox.Show("WaitForItToWorkAsyncTap complete: " + result.ToString());
}
A few words on threading. There is no additional threads explicitly created here. Internally, Task.Delay() implementation may use pool threads (I suspect they use Timer Queues), but in this particular example (a WinForms app), the continuation after await will happen on the same UI thread. In other execution environments (e.g. a console app), it might continue on a different thread. IMO, this article by Stephen Cleary is a must-read to understand async/await threading concepts.
If the task is asynchronous you can try with:
async Task WaitForItToWork()
{
await Task.Run(() =>
{
bool succeeded = false;
while (!succeeded)
{
// do work
succeeded = outcome; // if it worked, make as succeeded, else retry
System.Threading.Thread.Sleep(1000); // arbitrary sleep
}
});
}
See http://msdn.microsoft.com/en-us/library/hh195051.aspx.
Just provide another solution
public static void WaitForCondition(Func<bool> predict)
{
Task.Delay(TimeSpan.FromMilliseconds(1000)).ContinueWith(_ =>
{
var result = predict();
// the condition result is false, and we need to wait again.
if (result == false)
{
WaitForCondition(predict);
}
});
}
You don't really need WaitItForWork method, just await for a database initialization task:
async Task Run()
{
await InitializeDatabase();
// Do what you need after database is initialized
}
async Task InitializeDatabase()
{
// Perform database initialization here
}
If you have multiple pieces of code that call to WaitForItToWork then you need to wrap database initialization into a Task and await it in all workers, for example:
readonly Task _initializeDatabaseTask = InitializeDatabase();
async Task Worker1()
{
await _initializeDatabaseTask;
// Do what you need after database is initialized
}
async Task Worker2()
{
await _initializeDatabaseTask;
// Do what you need after database is initialized
}
static async Task InitializeDatabase()
{
// Initialize your database here
}

Categories

Resources