我是新来的异步编程,所以通过一些异步示例代码去后,我想编写一个简单的异步代码
我创建了一个简单的WinForm应用程序和表格里面我写了下面的代码。 但它只是不工作
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);
}
可能有人请点击这里放一些轻..
该方法的列出返回类型是Task<string>
。 你试图返回一个string
。 它们是不一样的,也没有从字符串的隐式转换Task<string>
,因此错误。
你可能有这种困惑async
方法,其返回值会自动包装在一个Task
由编译器。 目前,该方法不是异步方法。 你几乎肯定意味着要做到这一点:
private async Task<string> methodAsync()
{
await Task.Delay(10000);
return "Hello";
}
有两个关键的变化。 首先,该方法被标记为async
的,这意味着返回类型被包裹在一个Task
,使得该方法的编译。 接下来,我们不想做一个阻塞等待。 作为一般规则,使用时await
模型总是避免时,你可以阻止等待。 Task.Delay
是将指定的毫秒数日后可能完成的任务。 通过await
-ing这一任务,我们正在有效地进行非阻塞等待时间(实际上该方法的其余部分是工作的延续)。
如果你喜欢这样做,不使用的4.0方式await
,你可以这样做:
private Task<string> methodAsync()
{
return Task.Delay(10000)
.ContinueWith(t => "Hello");
}
第一个版本将编译下来的东西,就是这样或多或少,但会有一些额外的样板代码在他们的支持错误处理等功能await
我们没有充分利用这里。
如果你的Thread.Sleep(10000)
是真正的意思仅仅是对一些长期运行的方法的占位符,而不是仅仅等待了一段时间的方式,那么你需要确保工作在另一个线程中完成的,而不是当前上下文。 这样做的最简单的方法就是通过Task.Run
:
private Task<string> methodAsync()
{
return Task.Run(()=>
{
SomeLongRunningMethod();
return "Hello";
});
}
或者更可能的:
private Task<string> methodAsync()
{
return Task.Run(()=>
{
return SomeLongRunningMethodThatReturnsAString();
});
}
使用FromResult方法
public async Task<string> GetString()
{
System.Threading.Thread.Sleep(5000);
return await Task.FromResult("Hello");
}
除了问题使用async
由@Servy指出,另一个问题是,你需要明确获得T
的Task<T>
通过调用Task.Result。 需要注意的是Result属性将阻止异步代码,应慎重使用。
尝试:
private async void button1_Click(object sender, EventArgs e)
{
var s = await methodAsync();
MessageBox.Show(s.Result);
}