不能键入“串”隐式转换为“System.Threading.Tasks.Task “(Cann

2019-07-19 04:05发布

我是新来的异步编程,所以通过一些异步示例代码去后,我想编写一个简单的异步代码

我创建了一个简单的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);
}

可能有人请点击这里放一些轻..

Answer 1:

该方法的列出返回类型是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();
        });
}


Answer 2:

使用FromResult方法

public async Task<string> GetString()
{
   System.Threading.Thread.Sleep(5000);
   return await Task.FromResult("Hello");
}


Answer 3:

除了问题使用async由@Servy指出,另一个问题是,你需要明确获得TTask<T>通过调用Task.Result。 需要注意的是Result属性将阻止异步代码,应慎重使用。

尝试:

private async void button1_Click(object sender, EventArgs e)
{
    var s = await methodAsync();
    MessageBox.Show(s.Result);
}


文章来源: Cannot implicitly convert type 'string' to 'System.Threading.Tasks.Task'