无法将类型“string”隐式转换为“System.Threading.Tasks.Task<string>”

Posted

技术标签:

【中文标题】无法将类型“string”隐式转换为“System.Threading.Tasks.Task<string>”【英文标题】:Cannot implicitly convert type 'string' to 'System.Threading.Tasks.Task<string>' 【发布时间】:2013-01-17 10:56:53 【问题描述】:

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

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

有人可以在这里放点灯吗..

【问题讨论】:

【参考方案1】:

列出的方法返回类型是Task&lt;string&gt;。您正在尝试返回 string。它们不一样,也没有从字符串到Task&lt;string&gt;的隐式转换,因此出现错误。

您可能会将此与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();
        );

【讨论】:

我怎样才能将string 明确地包装在Task 中?或者在被调用的方法中不使用asyncawait(在这种情况下为methodAsync)有没有办法返回TaskTask&lt;T&gt; @Aniket 不,你错了,有很多方法可以在任务中显式包装字符串。我将在其中编辑解决方案。 @Servy:假设我没有使用延迟和其他代码,这导致methodAsync 中的延迟相同,我应该如何通过将结果字符串包装在任务中来返回结果字符串? 您可以使用 Task.FromResult 将字符串包装在 Task 中。 @dotNETbeginner 好吧,如果您不相信我,您可以自己尝试一下。 await 的意思是,启动该任务,一旦启动,就为该任务添加一个延续,并在异步任务完成后继续使用我停止的方法。如果你只是在异步方法中使用Sleep 然后Task.FromResult 它将花费整个 10 秒来启动任务,在它完成之前永远不会返回给调用者,从而一直阻塞 UI 线程并有效地运行整个事情同步进行。【参考方案2】:

使用 FromResult 方法

public async Task<string> GetString()

   System.Threading.Thread.Sleep(5000);
   return await Task.FromResult("Hello");

【讨论】:

谢谢,这正是我所需要的,没有提供其他答案。 据我所知,这个答案是实现使用同步实现的 Task 定义的接口的最佳方法【参考方案3】:

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

试试:

private async void button1_Click(object sender, EventArgs e)

    var s = await methodAsync();
    MessageBox.Show(s.Result);

【讨论】:

虽然这可能不被强烈推荐,但有一个实例我想在catch 中取回Task&lt;string&gt; 内容。我不能await.ToString() 产生不正确的结果。这符合要求。【参考方案4】:
    //source    
    public async Task<string> methodName()
            
             return Data;
             

    //Consumption
     methodName().Result;

希望这会有所帮助:)

【讨论】:

【参考方案5】:

就我而言。

        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;
    

【讨论】:

首先,这并不能回答所提出的问题。其次,这段代码确实有很多问题。非常奇怪的符号,在这个微小的方法中甚至不一致。将 Result() 调用显示为解决方案的一部分是另一个大问题。

以上是关于无法将类型“string”隐式转换为“System.Threading.Tasks.Task<string>”的主要内容,如果未能解决你的问题,请参考以下文章

无法将类型“System.DateTime”隐式转换为“string”

无法将类型“string”隐式转换为“System.Threading.Tasks.Task<string>”

无法将类型“字符串”隐式转换为“System.Data.SqlClient.Sqlconnection”

asp.net 无法将类型“System.DateTime”隐式转换为“string”

无法将类型“System.DateTime”隐式转换为“string”是啥意思?怎么改正?

新手:: 无法将类型“int”隐式转换为“string”