刚拿到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);
}
到目前为止,一切都很好。问题是当我调用 GetNameAsync时:
public static void DoStuff()
{
GetNameAsync();
MainWorkOfApplicationIDontWantBlocked();
}
关键GetNameAsync
在于它是异步的。我不想阻止它,因为我想尽快回到MainWorkOfApplicationIDontWantBlocked并让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();
}
但是现在我有了多余的代码。Visual Studio似乎了解到我被迫编写了这些不必要的代码,因为它抑制了正常的“从未使用过的值”警告。
我还可以通过将GetNameAsync包装在非异步方法中来摆脱警告:
public static Task GetNameWrapper()
{
return GetNameAsync();
}
但是,这甚至更多多余的代码。因此,我必须编写不需要的代码或容忍不必要的警告。
关于异步的使用我在这里有问题吗?
GetNameAsync
提供,是由用户提供(即全名Task<Name>
,而不是只返回一个Task
? DoStuff
然后可以存储任务,无论await
它之后的另一种方法,甚至是任务传递给其他方法,因此它可以await
或Wait
它里面的落实地方。
async
关键字。
PromptForStringAsync
您要做的工作比您需要做的要多;只返回的结果Task.Factory.StartNew
。值就是在控制台中输入的字符串已经是一项任务。无需等待它返回结果。这样做不会增加任何新价值。