I've used async methods for a long time, but I don't know the right way to write my own async method. As I get it, first root(I mean most deep) async method begins from sync method wrapped in a Task? Am I right? What is the right pattern to write such methods? Right now I do it like this:
private async Task DoSomethingAsync()
{
var tsk = new Task(OnDo);
tsk.Start();
await tsk.ConfigureAwait(false);
}
private void OnDo()
{
// Do stuff ...
}
The actual answer is too long to post here.
Short answer
No, you should not call async methods from sync methods. The method tree should be asynchronous bottom to top.
For example: Using ASP.NET MVC async methods would be called from async Action methods, see: Using Asynchronous Methods in ASP.NET MVC 4.
public async Task<ActionResult> GizmosAsync()
{
ViewBag.SyncOrAsync = "Asynchronous";
var gizmoService = new GizmoService();
return View("Gizmos", await gizmoService.GetGizmosAsync());
}
Using WPF applications, you should have async void event methods, that call your asynchronous methods.
private async void button1_Click(object sender, RoutedEventArgs e)
{
textBlock1.Text = "Click Started";
await DoWork();
textBlock2.Text = "Click Finished";
}
Either way, the question is too broad.
What is your "to be implemented" method?
why do you want it to be async?
What environment are you using?
In general async is used for I/O operations(databases, network, file read/write) or parallelism.
Related
I have a Task which I'm trying to run through OnIsActiveChanged So that it runs when I open as a view. I'm sure I'm doing something obvious but I'm relatively new to Async code.
I'm getting an error with OnIsActiveChanged telling me
Task SettingsView.OnIsActiveChanged(object?, EventArgs) has the wrong return type.
Here is the method I'm trying to use:
public async Task OnIsActiveChanged(object? sender, EventArgs e)
{
if (IsActive)
{
var streaming = _client.BiStreaming();
var requestStream = streaming.RequestStream;
var responseStream = streaming.ResponseStream;
//Print
Debug.WriteLine($"Duration: {Duration.TotalSeconds} seconds");
Debug.WriteLine("");
await BidirectionalStreamingExample(_client);
}
}
And here is where I am trying to call the method:
public SettingsView(SequenceEditorService.SequenceEditorServiceClient client)
{
InitializeComponent();
_client = client;
IsActiveChanged += OnIsActiveChanged;
}
IsActiveChanged is an event handler that checks if there is a change in the state if the view. It was fine with the normal method i had but once i tried to async it broke.
There are two possible solutions to your question, as we would need to know what kind of return type the IsActiveChanged-event has. Typically events should have no return type (void) according to BCL guidelines, the possibility still exists though.
Possible solutions:
You have to return a Task (very unlikely as stated above)
Set the OnIsActiveChanged's return type to void (likely the solution, since IsActiveChanged is probably a event coded by Microsoft and therefore complies with the BCL guidelines)
When applying the second solution to your code, the OnIsActiveChanged's signature should look something like this:
public async void OnIsActiveChanged(object sender, EventArgs e)
This question already has an answer here:
Async Await Running Synchronously
(1 answer)
Closed 2 years ago.
I do not understand when I read the Microsoft documents about async and await working, as it says
Async methods are intended to be non-blocking operations. An await
expression in an async method doesn’t block the current thread while
the awaited task is running. Instead, the expression signs up the rest
of the method as a continuation and returns control to the caller of
the async method.
so consider my code:
public Form1()
{
InitializeComponent();
AsyncTest();
Test(1);
}
private async void AsyncTest()
{
HttpClient client = new HttpClient();
var ss = TT(2);
var s = await ss;
for (int i = 0; i < 10; i++)
{
//loop
}
}
private async Task<int> TT(int i)
{
while (true)
{
if (i > 1000000000)
break;
i++;
}
return i;
}
}
when ever I call AsyncTest(), it just waits behind TT method as it specified with await key, but what does it mean it return control to the main caller??
it is not been returned to the form1, if TT is an infinite loop it just remains forever.
thanks
It seems to me you are a newbee to async-await. You violate several rules about how to use async-await.
To make a function async do the following:
Declare the function async
Return Task<TResult> instead of TResult; return Task instead of void
ONLY EXCEPTION: event handlers return void instead of Task
there should be one await inside your async function. Your compiler will warn you if you omit this.
Make sure that all async functions that you call are awaited for before you return
Guideline: let async be a suffix to your async functions. This allows you to create a sync and an async function that do the same: void MyTest() and Task MyTestAsync()
Following these rules, you can't call an async function from within a constructor. As you are using Winforms your code could be like this:
public Form1()
{
InitializeComponent();
}
public async void OnButton1_Clicked(object sender, ...)
{ // because this is an event handler the return value is void
// Start the first test and await until ready
await TestAsync();
// Start the second test and await until ready:
int i = await TestAsync(1);
}
If you call an async function you know that somewhere inside this function is an await. If you have meaningful things to do while the inner function is awaiting, do not await yet. Do your useful things after the call and await the returned Task as soon as you need the result:
public async void OnButton2_Clicked(object sender, ...)
{
// Start a test, but don't await yet
var task1 = TestAsync(1);
// if here, function TestAsync is awaiting somewhere
// it is not finished yet, so you can't use the result of it
// But you can do Something else:
DoSomethingElse();
// if here you really need the result of TestAsync, await for it
int i = await task1;
// if here you know that TestAsync is finished, i has the proper return value
}
You don't have to start and await the tasks one by one, you can start several tasks and await for them as soon as you need the results:
public async void OnButton3_Clicked(object sender, ...)
{
// start several tasks. Don't await yet:
var task1 = TestAsync(1);
var task2 = TestAsync(2);
var task3 = TestAsync(3);
DoSomethingElse();
// if here I need the results of all three tasks:
var myTasks = new Task[] {task1, task2, task3};
await Task.WhenAll(myTasks);
}
An article that really helped me understanding async-await is this interview with Eric Lippert, where he compares async-await with a cook making breakfast. If a cook has to wait for the water to boil, he doesn't wait idly, but looks around to see if he can do other things. Search somewhere in the middle for async-await.
Another article that helped me following the guidelines of async-await is Async and Await by the ever so helpful Stephen Cleary
To understand the question please take a look on the await calls and the definition of the function InitSyncContext() of the following example.
Based on that i would like to know how the program will behave on each scenario because i don't fully understand what´s the difference between calling await InitSyncContext(store) and having a await call inside without returning a Task.
For reference i did a research before and i found a similar example here however i think it's different in my case.
*The following code is a simplified example from a real world code just for demonstration purposes.
void Main()
{
Initializer();
}
private async void Initializer()
{
var store = InitLocalStore();
await InitSyncContext(store); // <-- Here, await call
InitFileSync(store);
}
// Here returns Task (without having a return inside. No compile errors)
private async Task InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
//------------- Second Method -------------
void Main()
{
Initializer();
}
private void Initializer()
{
var store = InitLocalStore();
InitSyncContext(store); // <-- Here without await call
InitFileSync(store);
}
// Here is void but with a async call inside
private async void InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
What's the difference between awaiting async Task function and calling await inside a void function?
This is perhaps a very big question is best served by reading the fine article Async/Await - Best Practices in Asynchronous Programming by Mr Stephen Cleary.
Some summary points:
Avoid async void - Prefer async Task methods over async void methods
See also
Cleary, S, "Async/Await - Best Practices in Asynchronous Programming", March 2013, Microsoft, https://msdn.microsoft.com/en-us/magazine/jj991977.aspx?f=255&MSPPError=-2147217396, retrieved 14/7/2016
What's the difference between awaiting async Task function and calling await inside a void function?
The whole world! Everything...and then some. Let's take a step back and start with some of the basics.
You should go "async all the way", i.e.; if you're returning an awaitable (Task or Task<T>) these should correctly use the async and await keywords.
There are several things that need to be clarified here. You should not have async void methods, instead you should have async Task - the exception being event handlers (where the delegates are predefined as non-task returning) and the like. Let's examine and pick apart method one (I'm going to ignore the Main entry points):
One
private async void Initializer()
{
var store = InitLocalStore();
await InitSyncContext(store); // <-- Here, await call
...
}
// Here returns Task (without having a return inside. No compile errors)
private async Task InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
You have an Initializer method that is immediately a code smell as it is async void. This should be async Task and it should have the "Async" suffix. Additionally, you have an InitSyncContext that takes on a store variable and invokes some client initialization work. The code smell here is that you are using async and await. This is not need on simple (single task) workloads like this. Instead you should simply use the return keyword. Example at the very bottom. Let's look at method two:
Two
private void Initializer()
{
var store = InitLocalStore();
InitSyncContext(store); // <-- Here without await call
...
}
// Here is void but with a async call inside
private async void InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
Things have officially gone from bad to worse! With the misconceptions of the asynchronous nomenclatures, we have assumed that since one method appeared to work "ok" without taking into account the best practices that another method could follow suit. You made the InitSyncContext method async void. The reason methods should not be async void is that they are fire-and-forget. The internal async state machine doesn't have a Task to latch onto and therefore the state is lost. When you remove the caller's await you are saying start this asynchronous operation but you do not care about it's results.
Here is the correct way to implement the desired functionality:
Correct
private async Task InitializerAsync()
{
var store = InitLocalStore();
await InitSyncContextAsync(store);
...
}
// Simply return the task that represents the async operation and let the caller await it
private Task InitSyncContextAsync(MobileServiceSQLiteStore store)
{
return Client.SyncContext.InitializeAsync(store);
}
A note about the Main method from your snippets, if this is part of a console application - the top-level entry point into your async stack would invoke either .Result or .Wait().
Further reading
https://msdn.microsoft.com/en-us/magazine/jj991977.aspx?f=255&MSPPError=-2147217396
In first example compiler generate something like this:
TheadPool.RunTask(()=>InitSyncContext(store)).ContinueWith(()=>InitFileSync(store))
At second — nothing interesting. Because nobody wait the end of the task. All calls will be in main thread exept await Client.SyncContext.InitializeAsync(store);
This question already has an answer here:
Can't await async extension method
(1 answer)
Closed 5 years ago.
i was learning how to use Async and Await c#. so i got a link http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx#BKMK_WhatHappensUnderstandinganAsyncMethod
from here i try to run the code from VS2012 IDE but getting error.
this function is raising error.
private void button1_Click(object sender, EventArgs e)
{
int contentLength = await AccessTheWebAsync();
label1.Text= String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
}
this line giving error await AccessTheWebAsync();
The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'
what i am doing the wrong. please guide me how to run the code. thanks
It very clearly states that you have to decorate your method with async. Like so:
// note the 'async'!
private async void button1_Click(object sender, EventArgs e)
Have a look here: async (C# Reference).
By using the async modifier, you specify that a method, lambda expression, or anonymous method is asynchronous. If you use this modifier on a method or expression, it's referred to as an async method.
You need to put async in your method, I modified your code since the Click event signature does not return int, and your method AccessTheWebAsync does, so I moved it to another method async that returns int, anyway I async and await are kind of syntactic sugar and is recommended that you take a look at what really happens to your code when you use these keywords, take a look here: http://www.codeproject.com/Articles/535635/Async-Await-and-the-Generated-StateMachine
private async void button1_Click(object sender, EventArgs e)
{
await ClickAsync();
}
private async Task<int> AccessTheWebAsync()
{
return await Task.Run(() =>
{
Task.Delay(10000); //Some heavy work here
return 3; //replace with real result
});
}
public async Task ClickAsync()
{
int contentLength = await AccessTheWebAsync();
label1.Text = String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
}
}
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.