87

我是异步编程的新手,所以在浏览了一些异步示例代码之后,我想到了编写一个简单的异步代码

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

有人可以在这里放一些灯吗..

4

5 回答 5

143

列出的方法返回类型是Task<string>. 您正在尝试返回一个string. 它们不一样,也没有从 string 到 的隐式转换Task<string>,因此出现错误。

您可能会将其与编译器async自动将返回值包装在 a 中的方法混淆。Task目前该方法不是异步方法。你几乎肯定是要这样做的:

private async Task<string> methodAsync() 
{
    await Task.Delay(10000);
    return "Hello";
}

有两个关键变化。首先,方法被标记为async,这意味着返回类型被包裹在 a 中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();
        });
}
于 2013-02-02T02:33:28.857 回答
55

使用 FromResult 方法

public async Task<string> GetString()
{
   System.Threading.Thread.Sleep(5000);
   return await Task.FromResult("Hello");
}
于 2016-06-02T11:22:25.487 回答
23

除了async@Servy 指出的有问题的使用之外,另一个问题是您需要通过调用Task.Result来显式T获取。Task<T>请注意,Result 属性将阻止异步代码,应谨慎使用。

尝试:

private async void button1_Click(object sender, EventArgs e)
{
    var s = await methodAsync();
    MessageBox.Show(s.Result);
}
于 2013-06-04T23:32:18.540 回答
-1
    //source    
    public async Task<string> methodName()
            {
             return Data;
             }

    //Consumption
     methodName().Result;

希望这可以帮助 :)

于 2020-04-28T17:34:29.047 回答
-1

就我而言。

        string ip = _GetStoreIpaddress().Result;


    private async Task<string> _GetStoreIpaddress()
    {
        string _store_iP = "";
        var Ip_address = await App.SQLiteDb.GetItemsAsync();
        if (Ip_address != null)
        {
            _store_iP = Ip_address.ToString();
        }

        return _store_iP;
    }
于 2022-01-16T12:34:07.737 回答