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);
}
}
Related
Here's my test code. With this code, my form will get stuck after executing task.Result (it's a "not yet computed" status).
I know this is bad programming style - but I'm curious what happened about this task.Result status.
Thanks.
private async Task<int> func()
{
await Task.Run(() =>
{
;
});
return 1;
}
private async void button1_Click(object sender, EventArgs e)
{
Task<int> task = func();
if (task.Result > 1)
{ ; }
await task;
}
From the documentation of Task.Result:
Remarks
Accessing the property's get accessor blocks the calling thread until the asynchronous operation is complete; it is equivalent to calling the Wait method.
By the time you await the task (which wouldn't jam your form) the task is already completed thanks to accessing .Result (which will jam your form)
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)
I have been working on a simple c# application that uses rest and Azure SQL Database. My app has two buttons one for saving new names and the second for showing them. the later doesn't react when i press it and i get the following error related to these parts GetRequest(); PostRequest(jsonPost);
private void Btn_Click(object sender, EventArgs e)
{
GetRequest();
}
private void Btn_Click(object sender, EventArgs e)
{
User user = new User(0, firstnameText.Text);
JavaScriptSerializer java = new JavaScriptSerializer();
String jsonPost = java.Serialize(user);
PostRequest(jsonPost);
}
}
Severity Code Description Project File Line Suppression State Detail Description
Warning CS4014 Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. PersonRegister C:\Users\User\Downloads\RestSolution\RestSolution\PersonRegister\Form1.cs 86 Active The current method calls an async method that returns a Task or a Task and doesn't apply the await operator to the result. The call to the async method starts an asynchronous task. However, because no await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't what you expect. Usually other aspects of the calling method depend on the results of the call or, minimally, the called method is expected to complete before you return from the method that contains the call.
An equally important issue is what happens to exceptions that are raised in the called async method. An exception that's raised in a method that returns a Task or Task is stored in the returned task. If you don't await the task or explicitly check for exceptions, the exception is lost. If you await the task, its exception is rethrown.
As a best practice, you should always await the call.
You should consider suppressing the warning only if you're sure that you don't want to wait for the asynchronous call to complete and that the called method won't raise any exceptions. In that case, you can suppress the warning by assigning the task result of the call to a variable.
Although the advice to always return Task from an async method, this is not possible for UI event handlers. As such you should rewrite your handler like this:
private async void Button1_Click(object sender, EventArgs e)
{
await GetRequest();
}
private async void Button2_Click(object sender, EventArgs e)
{
Person p = new Person(0, nameText.Text);
JavaScriptSerializer js = new JavaScriptSerializer();
String jsonPost = js.Serialize(p);
await PostRequest(jsonPost);
}
See here for more info.
Also, as an aside, you should declare one static instance of HttpClient for the entire application (as per MSDN docs).
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);
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.