Await operator can only be used within an Async method [duplicate] - c#

This question already has answers here:
Can't specify the 'async' modifier on the 'Main' method of a console app
(20 answers)
Closed 5 years ago.
I'm trying to make a simple program to test the new .NET async functionality within Visual Studio 2012. I generally use BackgroundWorkers to run time-consuming code asynchronously, but sometimes it seems like a hassle for a relatively simple (but expensive) operation. The new async modifier looks like it would be great to use, but unfortunately I just can't seem to get a simple test going.
Here's my code, in a C# console application:
static void Main(string[] args)
{
string MarsResponse = await QueryRover();
Console.WriteLine("Waiting for response from Mars...");
Console.WriteLine(MarsResponse);
Console.Read();
}
public static async Task<string> QueryRover()
{
await Task.Delay(5000);
return "Doin' good!";
}
I checked out some examples on MSDN and it looks to me like this code should be working, but instead I'm getting a build error on the line containing "await QueryRover();" Am I going crazy or is something fishy happening?

You can only use await in an async method, and Main cannot be async.
You'll have to use your own async-compatible context, call Wait on the returned Task in the Main method, or just ignore the returned Task and just block on the call to Read. Note that Wait will wrap any exceptions in an AggregateException.
If you want a good intro, see my async/await intro post.

Related

Await doesn't block calling thread [duplicate]

This question already has answers here:
How and when to use ‘async’ and ‘await’
(25 answers)
How do yield and await implement flow of control in .NET?
(5 answers)
Brief explanation of Async/Await in .Net 4.5
(3 answers)
Closed 2 years ago.
I never had a good chance to go deep into async/await , so I have just a gist of what it does.
So I tried it in WinForms app like this:
private async void button2_Click(object sender, EventArgs e)
{
// In below line I understand the Task is created and scheduled to execute, which in this
// simple case means, that it executes right away asynchronously.
var task = Task.Factory.StartNew(() =>
{
Task.Delay(5000).Wait();
return 12;
});
// Here we wait for the task to finish, so we don't see MessageBox yet.
var res = await task;
MessageBox.Show("Result is :" + res);
}
My question is, since we are waiting on await I expected to block UI thread, since we can go any further in that thread (to the line with MessageBox). So UI thread actually stops on method with event hadnler.
But, to my surprise, windows is responsive and everything works very well, but I didn't expect that. Can anybody explain me what is going on?
After reading this post, I still have a doubt, if await is asynchronous and doesn't block UI thread in my example, why the thread doesn't proceed to next line with MessageBox? How the UI thread proceeds then?
Is good idea that code after await is just another Task, like in ContinueWith? But it comes back to UI context?
Async methods are a lot like generator methods. The compiler will split up your code at each await operator. A block of code is inserted to check if the task is already complete, in which case the method immediately continues. Or if the task is not complete, a callback is registered to continue execution later, and your method returns.
Returning early is the whole point of an async method.

Calling async function with `function().Wait()` works, but `async function()` crashes

I'm calling a 3rd party library from my C# code, and have found that ctx.CreateSiteAsync(communicationSiteInfo).Wait(); works well, while await ctx.CreateSiteAsync(communicationSiteInfo); causes the application to crash. As .Wait() to the best of my knowledge causes the thread to block, I'm interested inn getting the await approach to work.
Here an extract from my code to put the above calls in context:
public async Task createSite(string base_url, SiteConfig siteConfig) {
using(var ctx = new OfficeDevPnP.Core.AuthenticationManager().GetAppOnlyAuthenticatedContext(base_url, this.applicationId, this.applicationSecret)) {
ctx.Load(ctx.Web, p => p.Title);
ctx.ExecuteQuery();
CommunicationSiteCollectionCreationInformation communicationSiteInfo = new CommunicationSiteCollectionCreationInformation {
Title = siteConfig.title,
Url = siteConfig.url,
SiteDesign = siteConfig.siteDesign,
Description = siteConfig.description,
Owner = siteConfig.ownerEmailAddress
};
try {
// This works: ctx.CreateSiteAsync(communicationSiteInfo).Wait();
await ctx.CreateSiteAsync(communicationSiteInfo);
} catch....
If I'm not mistaking, the function I'm calling it this one: ClientContextExtensions.cs.
I'm pretty new to C#, so perhaps the reason for the application crashing is obvious, but I can't see why the await wouldn't work, as the function I'm calling has async Task in it's definition.
EDIT: The weird thing regarding the exception is that the application simply crashes, and the catch clause is never reached. I don't know, but maybe this has something to do with threading or context or something in that the exception thrown in the async function call are not returned to the current thread. The application crashes on the await ctx.CreateSiteAsync(communicationSiteInfo); call.
EDIT 2: It looks as though I can simplify the issue at hand, but using this as an example instead:
public async Task StartMessageQueuePollAsync()
{
while (true)
{
await Task.Delay(1000).ConfigureAwait(false);
}
This causes the code to crash on await Task.Delay(1000).ConfigureAwait(false);. If is instead use Task.Delay(1000).Wait(), the code works as expected.
I see your answer, but I don't think that's the root cause. It's perfectly fine to use static async Task Main(), as long as your project is using C# 7.0 or higher (when that was introduced). If changing that (and making everything else synchronous, as you'd have to after removing async) made the symptom go away, then that means that somewhere along your call stack, you were missing an await.
For example, this works just fine:
using System;
using System.Threading.Tasks;
public class Program
{
public static async Task Main()
{
Console.WriteLine("Hello.");
await Pause();
Console.WriteLine("All done");
}
public static async Task Pause() {
await Task.Delay(1000);
Console.WriteLine("Done pausing");
}
}
But if you remove the await in Main, then the application would end before "Done pausing" is printed. This is because async methods run synchronously at first, but return at the first await that acts on an incomplete Task. (Pause() returns a Task when it hits await Task.Delay(1000) - before the waiting is completed)
So if you don't await an async method, then your code will just move on to the next line before the work is done. Sometimes you actually want this, but often not.
Since it otherwise runs synchronously, replacing the await with .Wait() would halt the thread and the method would not return, making it suddenly "work".
In your code, that means that either you weren't awaiting createSite() or weren't awaiting whatever called the method that called createSite(), etc.
Microsoft has a series of very well-written articles about asynchronous articles that are worth reading. Start here: Asynchronous programming with async and await
Thanks for the comments on my initial post. I got it working now, and believe it's because of I defined the Main method to be async, like this:
static async Task Main().

UI Received task got cancelled [duplicate]

This question already has answers here:
'await' works, but calling task.Result hangs/deadlocks
(6 answers)
Closed 3 years ago.
In my application, I am trying to update the user profile which calls the Rest API. API has one sync method UpdateProfile where execution getting stuck.
this line of code is ending the execution
command.UserProfile.LookupItems = GetLookupItemsByUserId(existingUser.Id).Result;
When i changed this line of code to
command.UserProfile.LookupItems = Task.Run(async () => await GetLookupItemsByUserId(existingUser.Id)).Result;
It started working without any issue.Can anybody explain to me what is going on behind the scene?
The first version is blocking the current thread, when the task complete the blocked thread cannot catch it.
YourType Signature() {
var neverUsedValue = task.Result;
}
The second one is yielding the current "thread" until the task is returned.
YourType Signature() {
var value = Task.Run(await => async MethodThatWillComplete()).Result
}
What you should do is propagate the async to the method:
async Task<YourType> SignatureAsync() {
command.UserProfile.LookupItems = await GetLookupItemsByUserId(existingUser.Id);
}
In this way you will avoid handling the AggregateException.
There is very well written article on this here:Don't block async
In a few words, blocking on async code is bad because it may be blocking the thread which is supposed to run the async code and thus generete a deadlock.

Trouble understanding need for async and await [duplicate]

This question already has answers here:
How and when to use ‘async’ and ‘await’
(25 answers)
Closed 5 years ago.
Yesterday, I learned the basics about C# multitasking. While I technically seem to understand how it works, I just don't see why it's done like it is. Bearing in mind that I'm new on the topic, that's probably a sign that I have understood something wrong. For example, You could write:
public async Task SomeEventHandler()
{ if(foo) return await SomeMethod("a");
else return await SomeMethod("b");
}
async Task<int> SomeMethod(string whatever)
{ string bar = await SomeInput();
return bar + " " + whatever;
}
What I don't see here is that why are the async and await keywords required? Why can't one just write:
public void SomeEventHandler()
{ if(foo) return SomeMethod("a");
else return SomeMethod("b");
}
int SomeMethod(string whatever)
{ string bar = SomeInput();
return bar + " " + whatever;
}
With the input method implementation being something like:
public string SomeInput()
{ while(!InputObject.stuffIncoming)
{ CurrentTheard.DoSomethingElse();
}
return InputObject.Next();
}
Can somebody explain why that would not work, or would work in undesirable way? EDIT: According to answers it seems to be that for some reason, methods doing awaiting cannot be called like regular ones or vice-versa. But what causes that? At least in D you can both call or spawn a theard for a same function.
The Idea behind async and await is to provide a simple way to implement a "parallel execution with callback" approach. Whenever the keyword await is used the execution of the next line of code is delayed until the current line is completed (just like in a normal execution) but the current Thread is not blocked. This means that behind the scenes the following is happening:
You call a long running operation with await
The long running operation is executed in another Thread
The rest of your methods code is registered as a callback method
the calling Thread goes on with execution after the method starting the long running operation
the long running operation eventually finishes
the callback method (from point 3) is executed
The benefit is, that your code will remain easy to read. You don't have to bother with Threads and callbacks

Akavache's GetObject<T> hangs when awaited. Any idea what is wrong here?

I have a Xamarin.Forms application, with this code in my App class (yes, this is just a sample to demonstrate the issue):
public App()
{
BlobCache.ApplicationName = "MyApp";
BlobCache.EnsureInitialized();
// The root page of your application
MainPage = GetMainPage();
}
public object BlockingGetExternalUser()
{
return GetExternalUser().Result;
}
private async Task<object> GetExternalUser()
{
try
{
return await BlobCache.LocalMachine.GetObject<object>("user");
}
catch (KeyNotFoundException)
{
return null;
}
}
The Key "user" does not exist, so I would expect to get a KeyNotFoundException. However I never see this exception being thrown. Instead it just "hangs" and never returns from the await GetObject call.
I am running this on my phone with Android 5.0.
Any ideas how to fix this? Am I doing something fundamentally wrong?
Update: On a side note: Instead of immediately trying GetObject, one could try to check if the key actually exists in the cache and only then retrieve it from the cache. However, if I am not mistaken, there is no other way to do a check other than calling GetObject and catching the exception like in the sample above. For a scenario where one would just want to know if an item exists, that doesn't seem to be ideal. Maybe an "Exists()" method would be a nice to have in Akavache? Or maybe I am missing something?
Update2: Changing the example to not use an async method in the constructor. Just to prove a point that that is not the issue.
Update3: Removing the call from the constructor. When I call BlockingGetExternalUser from anywhere in my code, the await will still hang.
You're most certainly having a dead-lock. Quoting Synchronously waiting for an async operation, and why does Wait() freeze the program here:
The await inside your asynchronous method is trying to come back to the UI thread.
Since the UI thread is busy waiting for the entire task to complete, you have a > deadlock.
Note that your call to .Result implies a Task.Wait() somewhere.
There are two solutions: Either completely avoid the async methods, or wrap your code into a Task.Run like this:
public object BlockingGetExternalUser()
{
return Task.Run<object>(() => GetExternalUser().Result);
}
(I hope it's compiling I didn't verify in VS :)
By experience I tend to avoid async methods in combination with SQLite these days. Reason is that most SQLite wrapper libraries use the Task.Run anti-pattern to provide async wrappers around their methods while SQLite doesn't have any intrinsic notations of being asynchronous. Note though that it's perfectly fine for you to wrap things into Task.Run to make them asynchronous and that it's only an anti-pattern for library designers, suggesting to their users that methods are asynchronous when they're actually not. You can read more about this here: Task.Run as an anti-pattern?
Using async methods in a constructors (var externalUser = GetExternalUser().Result;) is considered as a bad code. You shouldn't use async methods in a class constructors. Read this: Can constructors be async?
You could try to change it to avoid deadlocks:
Func<Task> task = async () => { await GetExternalUser().ConfigureAwait(false); };
task().Wait();
... but I won't recommend it.

Categories