I'm making a web call using the async framework. I'm getting an Error noted in the code below
class Program
{
static void Main(string[] args)
{
TestAsync async = new TestAsync();
await async.Go();//Error: the await operator can only be used with an async method. Consider markign this method with the async modifier. Consider applying the await operator to the result of the call
}
}
class TestAsync
{
public async Task Go()
{
using (WebClient client = new WebClient())
{
var myString = await client.DownloadStringTaskAsync("http://msdn.microsoft.com");
Console.WriteLine(myString);
}
}
}
I've tried several variations of this code. It either fails at runtime or does not compile. In this case the method completes before my async call is allowed to fire. What am I doing wrong?
My goal is to execute a call to a web site using WebClient in an async fashion. I want to return the result as a string and print it out using Console.WriteLine. If you feel more comfortable starting with code that executes simply change
await async.Go(); to async.Go(); The code will run, but Console.WriteLine will not be hit.
The error message is correctly telling you that await can only be used in async methods. But, you can't make Main() async, C# doesn't support that.
But async methods return Tasks, the same Task used in TPL since .Net 4.0. And Tasks do support synchronous waiting using the Wait() method. So, you can write your code like this:
class Program
{
static void Main(string[] args)
{
TestAsync async = new TestAsync();
async.Go().Wait();
}
}
Using Wait() is the right solution here, but in other cases, mixing synchronous waiting using Wait() and asynchronous waiting using await can be dangerous and can lead to deadlocks (especially in GUI applications or in ASP.NET).
The program is ending before the web request can complete. This is because the Main will not wait for the async operation to complete since it has nothing left to do.
I bet if you make the Main last longer, then Console.WriteLine will get called.
I'd try adding a sleep after the call to the async method - Thread.Sleep(500) - anything long enough to permit the web request to complete should work.
Related
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().
I'm trying to connect to a database that is running on MariaDB by using MySqlConnector. However, if I execute the basic code snippet from the specified website, my program terminates as soon as it comes to the asynchronous opening of the database connection (figured out by debugging). In general, the console window just pops on the screen and then immediately closes again.
I installed the MySqlConnector as described here via the NuGet package manager.
The synchronous versions of the asynchronous methods work without any problems, I receive the data as expected. A connection to another database did not work either.
This is my program:
static void Main(string[] args)
{
doSomeStuff();
}
public static async void doSomeStuff()
{
var connString = "Server=localhost;User ID=root;Password=password;Database=mysql";
using (var conn = new MySqlConnection(connString))
{
await conn.OpenAsync();
using (var cmd = new MySqlCommand("SELECT host FROM mysql.user", conn))
using (var reader = await cmd.ExecuteReaderAsync())
while (await reader.ReadAsync())
Console.WriteLine(reader.GetString(0));
}
Console.WriteLine("Finished!");
Console.ReadKey();
}
Why does this happen? Is there anything I'm missing? Perhaps something concerning the configuration on the server side?
Targeted Framework: .NET Framework 4.7.1
MySqlConnector version: 0.53.0
MariaDB version: 10.3.14
Your problem is that you are not awaiting the execution of the method doSomeStuff, so when it arrives to the first await, it returns the control to the main, and since there are no things left to do in main it returns ending the program.
You got 2 options here,
Is to run a main async awaiting a Task.delay(-1), execute first the method you have, and since you are awaiting a task that will never end you will get the job done.
Call your method like this doSomeStuff().GetAwaiter().GetResult() . This will await for the method to execute what it needs to and then return to the main thread. In order to achieve this you should change the signature of your method for an async task instead of an async void. (Best Option if using older c# versions)
Option 3 (best option if c# 7.1 or newer) by MickyD
https://stackoverflow.com/a/56078498/10513564
You biggest issue might be using the async void method, what happens with async voids is that when errors occur, your method silently dies(crashes app depending on location) and never tell you what the issue is,
A few article on the net explain this principle, on such is at https://haacked.com/archive/2014/11/11/async-void-methods/
In C#, async void methods are a scourge upon your code. To understand
why, I recommend this detailed Stephen Cleary article, Best Practices
in Asynchronous Programming. In short, exceptions thrown when calling
an async void method isn’t handled the same way as awaiting a Task and
will crash the process. Not a great experience.
Recently, I found another reason to avoid async void methods. While
investigating a bug, I noticed that the unit test that should have
ostensibly failed because of the bug passed with flying colors. That’s
odd. There was no logical reason for the test to pass given the bug.
Then I noticed that the return type of the method was async void. On a
hunch I changed it to async Task and it started to fail. Ohhhhh snap!
The are a few others that you can check on the net, async voids are mostly used for events, try changing the void into a Task and the error you are expecting will popup(at least you will have a starting point to figure out why your connection is failing)
Also if you are running an asynchronous in a synchronous one, then just do a Task.Run(() => doSomeStuff()).Result;
That will force your method to run to completion in a synchronous method if you do not have access to the await keyword
Considering you are using .NET Framework 4.7.1 you might want to consider forcing C# 7.1 in your project and make use of async Main(). It leads to much cleaner code without any ugly GetResult()/Result/Sleep/Task.Delay.
e.g.
class Program
{
// Specify C# 7.1 in the project's Properties.Build.Advanced.Language Version field
// in order to use 'static async Task Main'
static async Task Main(string[] args) // <--- Note the async Task
{
Console.WriteLine("Sleeping for 3 seconds");
// the await prevents the app from exiting prematurely
await Task.Delay(TimeSpan.FromSeconds(3));
}
}
If you get a compile error, you may need to force C# 7.1:
So, in your case change your code to:
static async Task Main(string[] args)
{
await doSomeStuff();
}
public static async Task doSomeStuff() // <--- make it Task so it can be await'ed
{
var connString = "Server=localhost;User ID=root;Password=password;Database=mysql";
using (var conn = new MySqlConnection(connString))
{
await conn.OpenAsync();
using (var cmd = new MySqlCommand("SELECT host FROM mysql.user", conn))
using (var reader = await cmd.ExecuteReaderAsync())
while (await reader.ReadAsync())
Console.WriteLine(reader.GetString(0));
}
Console.WriteLine("Finished!");
Console.ReadKey();
}
async void
Though mahlatse's warning about async void has merrit, it doesn't apply to your specific problem whereby the application is exiting prematurely due to not waiting for tasks to complete as opposed to an application exiting prematurely due to an exception being thrown from an async void method. Assuming the only difference between your synchronous code and the asynchorous code is the async and not say database connections your code should not be faulting.
I've been trying to understand async/await and Task in C# but have been failing spectacularly despite watching youtube videos, reading documentation and following a pluralsight course.
I was hoping someone might be able to help answer these slightly abstract questions to help my brain out.
1.Why do they say that async/await enables an 'asynchonrous' method when the async keyword on it's own does nothing and the await keyword adds a suspension point? Isn't adding a suspension point forcing the method to act synchronously, i.e. finish the task marked by the await before moving on.
2.Apparently you are not supposed to use async void except for event handlers, so how do you call an async method normally? It seems that in order to call an async method by using the await keyword, the method/class that is calling it itself needs to be marked as async. All the examples I've seen have 'initiated' an async void method with an event handler. How would you 'escape' this wrapping of async/await to run the method?
3.
public async Task SaveScreenshot(string filename, IWebDriver driver)
{
var screenshot = driver.TakeScreenshot();
await Task.Run(() =>
{
Thread.Sleep(2000);
screenshot.SaveAsFile(filename, ScreenshotImageFormat.Bmp);
Console.WriteLine("Screenshot saved");
});
Console.WriteLine("End of method");
}
Relating back to 1. this looks like a synchronous method. Execution pauses when it gets to Task.Run, therefore Console.WriteLine("End of method"); will not be executed until the task is finished. Maybe the whole method itself will be executed asynchronously at the point it is triggered in the code? But relating back to 2, you need to call this with an await otherwise you get the message 'Because this call is not awaited..' therefore adding an await will cause that execution point to be synchronous and so on and so.
Any help understanding this would be much appreciated.
Isn't adding a suspension point forcing the method to act synchronously, i.e. finish the task marked by the await before moving on.
No, the word you're thinking of is "sequential", not "synchronous". await results in asynchronous sequential code. "Sequential" meaning "one at a time"; "synchronous" meaning "blocking until completed".
how do you call an async method normally?
Using await.
How would you 'escape' this wrapping of async/await to run the method?
Ideally, you don't. You go async all the way. Modern frameworks (including ASP.NET MVC, Azure Functions / WebJobs, NUnit / xUnit / MSTest, etc) all allow you to have entry points that return Task. Less-modern frameworks (including WinForms, WPF, Xamarin Forms, ASP.NET WebForms, etc) all allow async void entry points.
So, ideally you do not call asynchronous code from synchronous code. This makes sense if you think about what asynchronous code is: the entire point of it is to not block the calling thread, so if you block the calling thread on asynchronous code, then you lose all the benefits of asynchronous code in the first place.
That said, there are rare situations where you do need to treat the code synchronously. E.g., if you are in the middle of a transition to async, or if you are constrained by a library/framework that is forcing your code to be synchronous and won't work with async void. In that case, you can employ one of the hacks in my article on brownfield async.
Your understanding is pretty good :). The main point you seem to be missing is that "asynchronous" methods in .NET mean methods that can stop execution without blocking the calling thread.
As you pointed out in (1), the async keyword basically enables the use of await and requires the return type to be void or Task/Task<T>. await just instructs the current method to suspend execution until the task is complete.
What you are missing here is that it suspends just the current method. It does not block the thread the method was executing on. This is important in cases like the UI thread of a WPF application. Suspend method execution and everything keeps running, block the thread and the application stops responding.
You usually want your async calls to go all the way to the top (like an event handler), this allows the most flexibility and prevents deadlock situations. However; you can wait for a Task returning method to complete with Wait:
someAsyncMethod.Wait()
Or get the return value:
var result = someAsyncMethod.Result;
Note that both of these are synchronous and block the calling thread. Doing this can cause deadlock if the async task is waiting for some other work on the calling thread to complete.
The above should answer your question in (3); the method itself appears to execute synchronously (this is the magic of await/async) but the task doesn't block the calling thread.
It is asynchronous because you don't have to wait the method to return. In your code, you may call the async method and save the task in a variable. Continue doing something else. Later, when the method result is needed, you await the response (task).
// Synchronous method.
static void Main(string[] args)
{
// Call async methods, but don't await them until needed.
Task<string> task1 = DoAsync();
Task<string> task2 = DoAsync();
Task<string> task3 = DoAsync();
// Do other stuff.
// Now, it is time to await the async methods to finish.
Task.WaitAll(task1, task2, task3);
// Do something with the results.
Console.WriteLine(task1.Result);
Console.ReadKey();
}
private static async Task<string> DoAsync()
{
Console.WriteLine("Started");
await Task.Delay(3000);
Console.WriteLine("Finished");
return "Success";
}
// Output:
// Started
// Started
// Started
// Finished
// Finished
// Finished
// Success
I am writing some awaitable methods and I found a lot of way to do so on the internet. So I came here to know what is really happening on each way, and if some ways must be banished.
As far as I know, there is two kind of awaitable methods:
Those which call other awaitable methods :
public async Task<Foo> GetFooAsync()
{
var foo = await TrulyGetFooAsync();
// Do stuff with foo
return foo;
}
I did not find any other way to do this and I think it is the right way. Tell me if I am wrong !
Those which only call non-awaitable methods :
And here the problems come in my mind.
For example, I saw this:
Exemple 1
public async Task<Foo> GetFooAsync()
{
return await Task.Run(() => TrulyGetFoo());
}
As far as I understand, the async/await keywords are useless and can be avoided to give this:
Exemple 2
public Task<Foo> GetFooAsync()
{
return Task.Run(() => TrulyGetFoo());
}
This last example is what I was doing until now. About that, is there a difference between:
Task.Run(() => TrulyGetFoo());
and
Task.Run((Foo)TrulyGetFoo); // I don't know if the cast is required at any time but in my code, it was
???
But I recently found this way:
Exemple 3
public Task<Foo> GetFooAsync()
{
TaskCompletionSource<Foo> tcs = new TaskCompletionSource<Foo>();
tcs.SetResult(TrulyGetFoo());
return tcs.Task;
}
If I understood properly, an awaitable method does not always run on another thread ??? My guess is the third example is providing this mecanism (but how ??? I only see synchronous code in the third example), when the examples 1 and 2 will always run on a worker thread ???
May be there is still another ways to write awaitable methods, so let me know about them.
For example, I saw [Task.Run wrappers around synchronous code]
This is a bad practice. I have a blog post that explains why Task.Run should not be used as a method implementation.
As far as I understand, the async/await keywords are useless and can be avoided
Yes, but I don't recommend eliding async/await in more complex methods.
I recently found [TaskCompletionSource<T>]
As noted in the comments, your code example is still synchronous.
To make it asynchronous, your code should start some operation and return TaskCompletionSource<T>.Task. Then later, whenever that operation completes, your completion handler should call TaskCompletionSource<T>.SetResult (or similar method). For an example, see TAP wrappers for EAP or TAP wrappers for WaitHandles.
TaskFactory.FromAsync is also a wrapper around TaskCompletionSource<T>, and is used for TAP wrappers for APM.
The short version is this: anything that returns a Task can be awaited inside an async code block.
public async Task MyAsyncMethod()
{
// do some stuff
await TrulyAsyncFoo();
// do some other stuff
return;
}
If awaiting the async call is the only thing the method does, you can simply return the task itself, which will be awaited "upstream":
public Task MyAsyncMethod()
{
return TrulyAsyncFoo();
}
As far as calling synchronous (non-async) code in an async method, there's nothing to it. Just call it like normal code:
public async Task MyAsyncMethod()
{
MySyncMethod();
await TrulyAsyncFoo();
MyOtherSyncMethod();
}
Doing Task.Run(() => Foo()) is almost always a code smell that you aren't doing async/await right. Writing async code is not the same thing as writing multithreaded code. Async is just a nice way of telling the compiler that you need to wait for some network- or IO-bound task to complete.
To sum up:
Await lets you write asynchronous and synchronous code side-by-side
Async should only be used to wait for network- or IO-bound tasks, not compute-bound tasks
Async methods should always return Task or Task<T>
Avoid async void
Avoid blocking using task.Wait() and task.Result in ASP.NET and other threaded applications unless you know what you are doing
I am using this for async events that manipulate my DB
private async void btnSave_Click(object sender, EventArgs e)
{
success = await someClass.someMethod(some args);
}
and the someMethod is a task like that:
public static async Task<someObject> someMethod(args)
{
//do something here
}
I had a situation recently where I had an ASP.NET WebAPI controller that needed to perform two web requests to another REST service inside its action method. I had written my code to have functionality separated cleanly into separate methods, which looked a little like this example:
public class FooController : ApiController
{
public IHttpActionResult Post(string value)
{
var results = PerformWebRequests();
// Do something else here...
}
private IEnumerable<string> PerformWebRequests()
{
var result1 = PerformWebRequest("service1/api/foo");
var result = PerformWebRequest("service2/api/foo");
return new string[] { result1, result2 };
}
private string PerformWebRequest(string api)
{
using (HttpClient client = new HttpClient())
{
// Call other web API and return value here...
}
}
}
Because I was using HttpClient all web requests had to be async. I've never used async/await before so I started naively adding in the keywords. First I added the async keyword to the PerformWebRequest(string api) method but then the caller complained that the PerformWebRequests() method has to be async too in order to use await. So I made that async but now the caller of that method must be async too, and so on.
What I want to know is how far down the rabbit hole must everything be marked async to just work? Surely there would come a point where something has to run synchronously, in which case how is that handled safely? I've already read that calling Task.Result is a bad idea because it could cause deadlocks.
What I want to know is how far down the rabbit hole must everything be
marked async to just work? Surely there would come a point where
something has to run synchronously
No, there shouldn't be a point where anything runs synchronously, and that is what async is all about. The phrase "async all the way" actually means all the way up the call stack.
When you process a message asynchronously, you're letting your message loop process requests while your truly asynchronous method runs, because when you go deep down the rabit hole, There is no Thread.
For example, when you have an async button click event handler:
private async void Button_Click(object sender, RoutedEventArgs e)
{
await DoWorkAsync();
// Do more stuff here
}
private Task DoWorkAsync()
{
return Task.Delay(2000); // Fake work.
}
When the button is clicked, runs synchronously until hitting the first await. Once hit, the method will yield control back to the caller, which means the button event handler will free the UI thread, which will free the message loop to process more requests in the meanwhile.
The same goes for your use of HttpClient. For example, when you have:
public async Task<IHttpActionResult> Post(string value)
{
var results = await PerformWebRequests();
// Do something else here...
}
private async Task<IEnumerable<string>> PerformWebRequests()
{
var result1 = await PerformWebRequestAsync("service1/api/foo");
var result = await PerformWebRequestAsync("service2/api/foo");
return new string[] { result1, result2 };
}
private async string PerformWebRequestAsync(string api)
{
using (HttpClient client = new HttpClient())
{
await client.GetAsync(api);
}
// More work..
}
See how the async keyword went up all the way to the main method processing the POST request. That way, while the async http request is handled by the network device driver, your thread returns to the ASP.NET ThreadPool and is free to process more requests in the meanwhile.
A Console Application is a special case, since when the Main method terminates, unless you spin a new foreground thread, the app will terminate. There, you have to make sure that if the only call is an async call, you'll have to explicitly use Task.Wait or Task.Result. But in that case the default SynchronizationContext is the ThreadPoolSynchronizationContext, where there isn't a chance to cause a deadlock.
To conclude, async methods shouldn't be processed synchronously at the top of the stack, unless there is an exotic use case (such as a Console App), they should flow asynchronously all the way allowing the thread to be freed when possible.
You need to "async all the way up" to the very top of the call stack, where you reach a message loop that can process all of the asynchronous requests.