刚拿到 VS2012试图掌握 async
。
假设我有一个从阻塞源获取一些值的方法。我不希望方法的调用方阻塞。我可以编写一个方法来接受一个回调函数,这个函数在值到达时被调用,但是因为我使用的是 C # 5,所以我决定让这个方法异步,这样调用者就不必处理回调函数了:
// 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();
});
}
下面是一个调用它的示例方法。如果 PromptForStringAsync
不是异步的,则此方法将需要在回调中嵌套回调。通过异步,我可以用一种非常自然的方式来编写我的方法:
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);
}
到目前为止一切顺利。问题是当我 打电话获得名字同步时:
public static void DoStuff()
{
GetNameAsync();
MainWorkOfApplicationIDontWantBlocked();
}
GetNameAsync
的关键在于它是异步的。我不用 想要来阻塞它,因为我想尽快回到 MainWorkOfApplicationIDontWantBlockedASAP,让 GetNameAsync 在后台完成它的工作。然而,以这种方式调用它会在 GetNameAsync
行给我一个编译器警告:
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.
我非常清楚“当前方法的执行在调用完成之前仍在继续”。这是异步代码的 点对吧?
我更喜欢在没有警告的情况下编译我的代码,但是这里没有什么需要“修复”的地方,因为代码正在做我希望它做的事情。我可以通过存储 GetNameAsync
的返回值来消除这个警告:
public static void DoStuff()
{
var result = GetNameAsync(); // supress warning
MainWorkOfApplicationIDontWantBlocked();
}
但现在我有多余的代码了。VisualStudio 似乎理解我是被迫编写这些不必要的代码的,因为它抑制了正常的“值从未使用”警告。
我还可以通过将 GetNameAsync 包装在一个非异步的方法中来消除这个警告:
public static Task GetNameWrapper()
{
return GetNameAsync();
}
但这甚至是 更多多余的代码。所以我必须编写我不需要或容忍不必要的警告的代码。
我使用异步有什么问题吗?