我是异步编程的新手,所以在浏览了一些异步示例代码之后,我想到了编写一个简单的异步代码
我创建了一个简单的Winform应用程序,并在Form中编写了以下代码。但它只是不起作用
private Task<string> methodAsync() {
Thread.Sleep(10000);
return "Hello"; //Error: Cannot implicitly convert type 'string' to 'System.Threading.Tasks.Task<string>'
}
private async void button1_Click(object sender, EventArgs e)
{
string s = await methodAsync();
MessageBox.Show(s);
}
请有人在这里说清楚..
答案 0 :(得分:94)
列出的方法返回类型为Task<string>
。您正在尝试返回string
。它们不一样,也没有从字符串到Task<string>
的隐式转换,因此错误。
您可能会将此与async
方法混淆,其中返回值由编译器自动包装在Task
中。目前该方法不是异步方法。你几乎肯定会这样做:
private async Task<string> methodAsync()
{
await Task.Delay(10000);
return "Hello";
}
有两个关键变化。首先,该方法标记为async
,这意味着返回类型包含在Task
中,使方法编译。接下来,我们不想做阻塞等待。作为一般规则,使用await
模型时,请始终避免阻止等待。 Task.Delay
是在指定的毫秒数后完成的任务。通过await
- 我们正在有效地执行该任务的非阻塞等待(实际上,该方法的其余部分是该任务的延续)。
如果你喜欢4.0的方式而不使用await
,你可以这样做:
private Task<string> methodAsync()
{
return Task.Delay(10000)
.ContinueWith(t => "Hello");
}
第一个版本将编译成或多或少像这样的东西,但它会有一些额外的样板代码用于支持错误处理和我们没有在这里利用的await
的其他功能。 / p>
如果你的Thread.Sleep(10000)
真的只是一个长期运行方法的占位符,而不是等待一段时间的方式,那么你需要确保工作在另一个方法完成线程,而不是当前的上下文。最简单的方法是Task.Run
:
private Task<string> methodAsync()
{
return Task.Run(()=>
{
SomeLongRunningMethod();
return "Hello";
});
}
或更有可能:
private Task<string> methodAsync()
{
return Task.Run(()=>
{
return SomeLongRunningMethodThatReturnsAString();
});
}
答案 1 :(得分:29)
使用FromResult方法
public async Task<string> GetString()
{
System.Threading.Thread.Sleep(5000);
return await Task.FromResult("Hello");
}
答案 2 :(得分:19)
除了@Servy指出的async
的问题使用之外,另一个问题是你需要通过调用Task.Result从T
显式获取Task<T>
。请注意,Result属性将阻止异步代码,应谨慎使用。
尝试:
private async void button1_Click(object sender, EventArgs e)
{
var s = await methodAsync();
MessageBox.Show(s.Result);
}
答案 3 :(得分:-1)
//source
public async Task<string> methodName()
{
return Data;
}
//Consumption
methodName().Result;
希望这会有所帮助:)