【问题标题】:How can I use Tasks correctly?如何正确使用任务?
【发布时间】:2016-03-17 10:46:37
【问题描述】:
private async Task<List<PingReply>> PingAsync()
{
    Ping pingSender = new Ping();
    var tasks = serverNames.Select(ip => pingSender.SendPingAsync(ip, 2000));
    var results = await Task.WhenAll(tasks);

    return results.ToList();
}

我的问题是如何执行这个方法?

我试过了

 List<string> data = PingAsync();

但我收到此错误消息

Error   CS0029  Cannot implicitly convert type 'System.Threading.Tasks.Task<System.Collections.Generic.List<System.Net.NetworkInformation.PingReply>>' to 'System.Collections.Generic.List<string>' ServerManager   

我正在尝试 ping 服务器并更新 UI,以便我们可以监控服务器。

我也试过这些

        Task<PingReply> longRunningTask = PingAsync();
        PingReply result = await longRunningTask;

错误

严重性代码描述项目文件行抑制状态 错误 CS4033 'await' 运算符只能在异步中使用 方法。考虑用'async'修饰符标记这个方法和 将其返回类型更改为“任务”。服务器管理器

严重性代码描述项目文件行抑制状态 错误 CS0029 无法隐式转换类型 'System.Threading.Tasks.Task>' 到 'System.Threading.Tasks.Task' 服务器管理器

【问题讨论】:

  • 你需要等待那个方法List&lt;string&gt; data = await PingAsync();
  • 我认为您应该尝试理解错误消息,因为按照书面说明,这不可能工作。无论如何,您迟早需要了解这一点。
  • 您可能会发现这很有用msdn.microsoft.com/en-us/library/hh191443.aspx

标签: c# task


【解决方案1】:

查看您的 PingAsync 方法签名。它返回什么? Task&lt;List&lt;PingReply&gt;&gt;。添加async关键字并不会改变该类型,假设它基本上允许您在方法内部使用await

因此,通过调用PingAsync,您将获得Task&lt;List&lt;PingReply&gt;&gt; 类型的对象,并尝试将其分配给List&lt;string&gt; 引用——这会给您一个类型不匹配错误。

但是,您可能会问,如何从Task&lt;T&gt; 获得实际的T?你应该简单地使用await,就像你在你的方法中调用Task.WhenAll一样。

List&lt;PingReply&gt; data = await PingAsync();

【讨论】:

  • 感谢您的洞察力。但是,如果我从私有 void 方法执行,我会收到一条错误消息,说“等待”操作符只能在异步方法中使用
  • async 有时可能会让人感到困惑......基本上,您永远不应该使用 async void 方法(事件处理程序除外)。因此,您很可能应该将您的 async void fooAsync() 更改为 async Task fooAsync()
  • 他也可以data = PingAsync().Result; 为什么/为什么不呢?使用 await 有什么不同?
  • 我做了那个 data = PingAsync().Result 并且应用程序崩溃说 ArguementException 未处理。内部消息说“{”Value cannot be null.\r\nParameter name: source“}”
【解决方案2】:

错误信息本身就很清楚了。方法签名返回Task&lt;List&lt;PingReply&gt;&gt;,但由于某种原因,您希望它返回List&lt;string&gt;Task&lt;PingReply&gt;,不知道为什么。

您应该注意,在您的代码中开始使用async 会使它像瘟疫一样传播开来。这意味着调用异步方法的更高级别的方法通常需要自己为async 并返回TaskTask&lt;T&gt;

【讨论】:

    【解决方案3】:

    给定这个异步函数

    private async Task<List<PingReply>> PingAsync()
    {
        Ping pingSender = new Ping();
        var tasks = serverNames.Select(
                ip => pingSender.SendPingAsync(ip, 2000)
        );
        var results = await Task.WhenAll(tasks);
        return results.ToList();
    }
    

    从对象的其他部分调用,接受 TASK 包装的值

     Task<List<PingReply>> foo = PingAsync();
    

    然后手动等待...

    foo.Wait();
    

    然后提取值

    List<PingReply> bar = foo.Result;
    

    【讨论】:

    • 需要更多细节,这似乎是问题的设置,但缺少实际问题。
    猜你喜欢
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    • 2013-09-21
    相关资源
    最近更新 更多