Just got VS2012 and trying to get a handle on async
.
Let's say I've got an method that fetches some value from a blocking source. I don't want caller of the method to block. I could write the method to take a callback which is invoked when the value arrives, but since I'm using C# 5, I decide to make the method async so callers don't have to deal with callbacks:
// contrived example (edited in response to Servy's comment)
public static Task<string> PromptForStringAsync(string prompt)
{
return Task.Factory.StartNew(() => {
Console.Write(prompt);
return Console.ReadLine();
});
}
Here's an example method that calls it. If PromptForStringAsync
wasn't async, this method would require nesting a callback within a callback. With async, I get to write my method in this very natural way:
public static async Task GetNameAsync()
{
string firstname = await PromptForStringAsync("Enter your first name: ");
Console.WriteLine("Welcome {0}.", firstname);
string lastname = await PromptForStringAsync("Enter your last name: ");
Console.WriteLine("Name saved as '{0} {1}'.", firstname, lastname);
}
So far so good. The problem is when I call GetNameAsync:
public static void DoStuff()
{
GetNameAsync();
MainWorkOfApplicationIDontWantBlocked();
}
The whole point of GetNameAsync
is that it's asynchronous. I don't want it to block, because I want to get back to the MainWorkOfApplicationIDontWantBlocked ASAP and let GetNameAsync do its thing in the background. However, calling it this way gives me a compiler warning on the GetNameAsync
line:
Warning 1 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.
I'm perfectly aware that "execution of the current method continues before the call is completed". That's the point of asynchronous code, right?
I prefer my code to compile without warnings, but there's nothing to "fix" here because the code is doing exactly what I intend it to do. I can get rid of the warning by storing the return value of GetNameAsync
:
public static void DoStuff()
{
var result = GetNameAsync(); // supress warning
MainWorkOfApplicationIDontWantBlocked();
}
But now I have superfluous code. Visual Studio seems to understand that I was forced to write this unnecessary code, because it suppresses the normal "value never used" warning.
I can also get rid of the warning by wrapping GetNameAsync in a method that's not async:
public static Task GetNameWrapper()
{
return GetNameAsync();
}
But that's even more superfluous code. So I have to write code I don't need or tolerate an unnecessary warning.
Is there something about my use of async that's wrong here?
PromptForStringAsync
you do more work than you need to; just return the result ofTask.Factory.StartNew
. It's already a task who's value is the string entered in the console. There's no need to await it an return the result; doing so adds no new value. – ServyGetNameAsync
to provide the full name that was provided by the user (i.e.Task<Name>
, rather than just returning aTask
?DoStuff
could then store that task, and eitherawait
it after the other method, or even pass the task to that other method so it couldawait
orWait
it somewhere inside of it's implementation. – Servyasync
keyword. – Servy