无法从 Task<> 隐式转换类型

Posted

技术标签:

【中文标题】无法从 Task<> 隐式转换类型【英文标题】:Cannot implicitly convert type from Task<> 【发布时间】:2012-10-04 21:24:19 【问题描述】:

我正在尝试掌握 .NET 4.5 中的异步方法语法。我以为我已经完全理解了这些示例,但是无论异步方法的类型是什么(即Task&lt;T&gt;),在转换回T 时我总是会遇到相同类型的错误错误——我理解的差不多自动的。以下代码产生错误:

无法将类型“System.Threading.Tasks.Task&lt;System.Collections.Generic.List&lt;int&gt;&gt;”隐式转换为“System.Collections.Generic.List&lt;int&gt;

public List<int> TestGetMethod()

    return GetIdList(); // compiler error on this line



async Task<List<int>> GetIdList()

    using (HttpClient proxy = new HttpClient())
    
        string response = await proxy.GetStringAsync("www.test.com");
        List<int> idList = JsonConvert.DeserializeObject<List<int>>();
        return idList;
    

如果我也明确地转换结果,它也会失败。这个:

public List<int> TestGetMethod()

    return (List<int>)GetIdList();  // compiler error on this line

在某种程度上会导致此错误:

无法将类型“System.Threading.Tasks.Task&lt;System.Collections.Generic.List&lt;int&gt;&gt;”转换为“System.Collections.Generic.List&lt;int&gt;

非常感谢任何帮助。

【问题讨论】:

Task 到 T 的“自动展开”是等待任务的效果。如果您将 TestGetMethod 更改为异步,则它可以等待 GetIdList() 将 T 放入本地 var 不相关,但惯例会推荐 GetIdListAsync() 虽然对于内部使用来说没什么大不了的,当然。 :) 感谢您的回复詹姆斯。我之前曾尝试过,但如果我将 GetTestMethod() 更改为使用 await,那么它也必须是异步的,所以我还需要将其类型更改为 Task>。然后它的调用者会和现在的 GetTestMethod() 有同样的问题? 好的,我想我现在明白了 - 如果我让 GetTestMethod() 无效,那么这不会发生。但是只要一个方法有返回类型,它的调用者也必须是异步的,并且在调用中使用等待等。 当你调用返回任务的东西时,你没有使用等待。这实际上取决于调用者应该如何处理它。开火就忘了?安排继续吗?阻塞直到完成?还有什么?对于测试方法,假设您可以使用支持异步测试方法的测试框架,我会在异步测试方法中使用 await,但还有其他选择。 【参考方案1】:

您的示例的主要问题是您无法将 Task&lt;T&gt; 返回类型隐式转换为基本 T 类型。您需要使用 Task.Result 属性。请注意,Task.Result 将阻塞异步代码,应谨慎使用。

试试这个:

public List<int> TestGetMethod()  
  
    return GetIdList().Result;  

【讨论】:

Result could easily cause deadlocks. 完美运行 @Stephen Cleary 真的 它可以完美运行,直到死锁。【参考方案2】:

您还需要创建 TestGetMethod async 并在 GetIdList(); 前面附加 await 会将任务解包到 List&lt;int&gt;,因此,如果您的辅助函数返回 Task,请确保您在调用函数时已等待 @ 987654324@也是。

public Task<List<int>> TestGetMethod()

    return GetIdList();
    

async Task<List<int>> GetIdList()

    using (HttpClient proxy = new HttpClient())
    
        string response = await proxy.GetStringAsync("www.test.com");
        List<int> idList = JsonConvert.DeserializeObject<List<int>>();
        return idList;
    

另一种选择

public async void TestGetMethod(List<int> results)

    results = await GetIdList(); // await will unwrap the List<int>

【讨论】:

请注意,因为在这个 TestGetMethod 中没有其他任何事情发生,所以 unwrap+rewrap 有点傻,它可以删除 async 和 await 并返回 GetIdList() :) TestGetMethod 必须是 async 有什么要求?【参考方案3】:

根据您要执行的操作,您可以使用 GetIdList().Result 阻止(通常是个坏主意,但很难说出上下文)或使用支持异步测试方法并具有测试方法 do var results = await GetIdList();

【讨论】:

【参考方案4】:

我刚刚弹出了同样的问题,但解决方案与其他问题不同。我正在使用异步方法中的两个异步调用,这段代码给了我错误:

var fileContents = reader.ReadToEndAsync();
if (fileContents != null)

     var profile = await Task.Run(() => JsonConvert.DeserializeObject<T>(fileContents));
     return profile;

这是解决方法。我忘记了第一行的异步:

var fileContents = await reader.ReadToEndAsync();
if (fileContents != null)

     var profile = await Task.Run(() => JsonConvert.DeserializeObject<T>(fileContents));
     return profile;

错误消息显示在 var profile = ... 行的“fileContents”上,因此无法立即看出错误在哪里。

【讨论】:

以上是关于无法从 Task<> 隐式转换类型的主要内容,如果未能解决你的问题,请参考以下文章

不能隐式转换类型'System.Threading.tasks.task 至

无法将类型“IEnumerable<T>”隐式转换为“ActionResult<IEnumerable<T>>”

无法将类型 IAsyncOperation<StorageFile> 隐式转换为 StorageFile

无法将类型“System.Linq.IQueryable<int>”隐式转换为“int?”

使用带有约束的泛型时无法隐式转换类型[重复]

显示转换和隐式转换