等待一些任务完成(Task.WhenSome)

时间:2019-05-10 10:57:32

标签: c# task task-parallel-library

我正在编写一项服务,该服务结合了来自各种Internet来源的数据,并即时生成了响应。速度比完整性更为重要,因此,我想在一些(不是全部)互联网资源做出回应后立即做出回应。通常,我的服务会创建10个并发的Web请求,并且应停止等待并在其中5个请求完成后开始处理。 .NET Framework或我所知的任何第三方库都没有提供此功能,因此我可能必须自己编写。我尝试实现的方法具有以下签名:

public static Task<TResult[]> WhenSome<TResult>(int atLeast, params Task<TResult>[] tasks)
{
    // TODO
}

Task.WhenAny的工作方式相反,应该吞下异常,只要已获得所需数量的结果即可。但是,如果在完成所有任务之后没有足够的收集结果,则应抛出AggregateException以传播所有异常。

用法示例:

var tasks = new Task<int>[]
{
    Task.Delay(100).ContinueWith<int>(_ => throw new ApplicationException("Oops!")),
    Task.Delay(200).ContinueWith(_ => 10),
    Task.Delay(Timeout.Infinite).ContinueWith(_ => 0, new CancellationTokenSource(300).Token),
    Task.Delay(400).ContinueWith(_ => 20),
    Task.Delay(500).ContinueWith(_ => 30),
};
var results = await WhenSome(2, tasks);
ConsolePrint($"Results: {String.Join(", ", results)}");

预期输出:

  

结果:1​​0,20

在此示例中,返回值30的最后一个任务应该被忽略(甚至没有等待),因为我们已经获得了想要的结果数(2个结果)。出于相同的原因,也应该忽略已失败和已取消的任务。

1 个答案:

答案 0 :(得分:0)

这是一些笨拙的代码,我认为这些代码可以满足您的要求。这可能是一个起点。

这可能也是处理任务的一种不好的方式,并且/或者不是线程安全的,并且/或者只是一个糟糕的主意。但我希望有人能指出这一点。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite /$1 break;
      rewrite /shiny/(.*) /$1 break;
spec:
  rules:
    - http:
        paths:
          - path: /
            backend:
              serviceName: web
              servicePort: 80
          - path: /shiny
            backend:
              serviceName: shiny
              servicePort: 3838