任务并行库了WaitAny与特定的结果 [英] Task Parallel Library WaitAny with specified result

查看:201
本文介绍了任务并行库了WaitAny与特定的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试着写一些code,这将使Web服务调用了一些并行不同的服务器,因此TPL似乎是显而易见的选择使用。

只有我的Web服务调用一会再回到我想要的结果,所有的人则不会。我试图找出有效有一个 Task.WaitAny ,但只有疏通当第一个工作的一种方式符合条件的回报。

我试着用了WaitAny ,但不能工作了放在哪里过滤器。我得到了这个远:

 公共无效SearchServers()
{
    VAR服务器=新[] {服务器1,服务器2,服务器3,服务器4};
    VAR任务=服务器
                 。选择(S = GT;任务<布尔> .Factory.StartNew(服务器=> CallServer((字符串)服务器),S))
                 .ToArray();    Task.WaitAny(任务); //我怎么说了WaitAny,其中结果为真?    //省略:取消所有未完成的任务,因为正确的服务器已被发现
}私人布尔CallServer(字符串服务器)
{
    // ...拨打电话到服务器并返回结果...
}

修改:快速澄清,以防万一有上述任何混淆。我试图做到以下几点:


  1. 对于每一台服务器,启动工作来检查

  2. 不管,等到服务器返回true(只有1个服务器的最大永远不会返回true)

  3. 或者,等到所有的服务器都返回false,即存在不匹配。


解决方案

最好的是我能想到的是指定一个 ContinueWith 每个任务,检查结果,如果真正取消其他任务。对于取消的任务,你可能要使用的CancellationToken

  VAR任务=服务器
    。选择(S = GT; Task.Run(...)
        .ContinueWith(T =>
            如果(t.Result){
                //取消其他线程
            }
        )
    ).ToArray();

更新:另一种解决办法是将了WaitAny ,直至正确的任务完成(但它也有一些缺点,例如,从列表中删除完成的任务,并创建一个新的数组出其余的是相当沉重的操作):

 列表<任务<布尔>>任务= servers.Select(S =>任务&下;布尔> .Factory.StartNew(服务器= GT; CallServer((字符串)服务器)中,s))了ToList();布尔结果;
做{
    INT IDX = Task.WaitAny(tasks.ToArray());
    结果=任务[IDX]。结果;
    tasks.RemoveAt(IDX);
}而(导致&安培;!&安培; tasks.Count大于0);//取消其他任务

I'm trying to write some code that will make a web service call to a number of different servers in parallel, so TPL seems like the obvious choice to use.

Only one of my web service calls will ever return the result I want and all the others won't. I'm trying to work out a way of effectively having a Task.WaitAny but only unblocking when the first Task that matches a condition returns.

I tried with WaitAny but couldn't work out where to put the filter. I got this far:

public void SearchServers()
{
    var servers = new[] {"server1", "server2", "server3", "server4"};
    var tasks = servers
                 .Select(s => Task<bool>.Factory.StartNew(server => CallServer((string)server), s))
                 .ToArray();

    Task.WaitAny(tasks); //how do I say "WaitAny where the result is true"?

    //Omitted: cancel any outstanding tasks since the correct server has been found
}

private bool CallServer(string server)
{
    //... make the call to the server and return the result ...
}

Edit: Quick clarification just in case there's any confusion above. I'm trying to do the following:

  1. For each server, start a Task to check it
  2. Either, wait until a server returns true (only a max of 1 server will ever return true)
  3. Or, wait until all servers have returned false, i.e. there was no match.

解决方案

The best of what I can think of is specifying a ContinueWith for each Task, checking the result, and if true cancelling the other tasks. For cancelling tasks you may want to use CancellationToken.

var tasks = servers
    .Select(s => Task.Run(...)
        .ContinueWith(t =>
            if (t.Result) {
                // cancel other threads
            }
        )
    ).ToArray();

UPDATE: An alternative solution would be to WaitAny until the right task completed (but it has some drawbacks, e.g. removing the finished tasks from the list and creating a new array out of the remaining ones is quite a heavy operation):

List<Task<bool>> tasks = servers.Select(s => Task<bool>.Factory.StartNew(server => CallServer((string)server), s)).ToList();

bool result;
do {
    int idx = Task.WaitAny(tasks.ToArray());
    result = tasks[idx].Result;
    tasks.RemoveAt(idx);
} while (!result && tasks.Count > 0);

// cancel other tasks

这篇关于任务并行库了WaitAny与特定的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆