在ASP.NET中限制异步任务,对N个成功任务的限制 [英] Throttling asynchronous tasks in asp .net, with a limit on N successful tasks

查看:73
本文介绍了在ASP.NET中限制异步任务,对N个成功任务的限制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Asp .Net 4.5.1.我有要运行的任务,这称为Web服务,有些可能会失败.我需要运行N个成功的任务,这些任务执行少量的CPU工作,并且主要调用网络服务,然后停止,并且我想节流.

I'm using Asp .Net 4.5.1. I have tasks to run, which call a web-service, and some might fail. I need to run N successful tasks which perform some light CPU work and mainly call a web service, then stop, and I want to throttle.

例如,假设某个集合中有300个URL.我们需要运行一个名为 Task< bool>的函数.每一个上的CheckUrlAsync(url)都具有节流功能,例如,意味着同时"仅运行5个(换句话说,在任何给定时间最多使用5个连接).另外,我们只想执行N次(假设100次)成功的操作,然后停止.

For example, let's assume we have 300 URLs in some collection. We need to run a function called Task<bool> CheckUrlAsync(url) on each of them, with throttling, meaning, for example, having only 5 run "at the same time" (in other words, have maximum 5 connections used at any given time). Also, we only want to perform N (assume 100) successful operations, and then stop.

我已阅读

I've read this and this and still I'm not sure what would be the correct way to do it.

你会怎么做?

  1. 假设 ASP .Net
  2. 承担 IO呼叫(http对Web服务的呼叫),无需繁重的CPU操作.
  1. Assume ASP .Net
  2. Assume IO call (http call to web serice), no heavy CPU operations.

推荐答案

使用Semaphore slim.

Use Semaphore slim.

var semaphore = new SemaphoreSlim(5);
var tasks = urlCollection.Select(async url => 
{
    await semaphore.WaitAsync();
    try
    {
        return await CheckUrlAsync(url);
    } 
    finally 
    {
        semaphore.Release();
    }
};
while(tasks.Where(t => t.Completed).Count() < 100)
{
    await.Task.WhenAny(tasks);
}

尽管我更喜欢使用Rx.Net来生成一些更好的代码.

Although I would prefer to use Rx.Net to produce some better code.

using(var semaphore = new SemaphoreSlim(5))
{
    var results = urlCollection.ToObservable()
              .Select(async url => 
    {
        await semaphore.WaitAsync();
        try
        {
            return await CheckUrlAsync(url);
        } 
        finally 
        {
            semaphore.Release();
        }
    }).Take(100).ToList();
}

好吧...这将很有趣.

Okay...this is going to be fun.

public static class SemaphoreHelper
{
    public static Task<T> ContinueWith<T>(
         this SemaphoreSlim semaphore, 
         Func<Task<T>> action)
    var ret = semaphore.WaitAsync()
                   .ContinueWith(action);
    ret.ContinueWith(_ => semaphore.Release(), TaskContinuationOptions.None);
    return ret;
}
var semaphore = new SemaphoreSlim(5);
var results = urlCollection.Select(
              url => semaphore.ContinueWith(() => CheckUrlAsync(url)).ToList();

我确实需要补充一点,代码本身仍将运行所有300个URL,返回的速度更快...仅此而已.您需要将取消令牌添加到 semaphore.WaitAsync(token)中,以取消排队的工作.我再次建议为此使用Rx.Net.使用Rx.Net可以更轻松地使取消令牌与 .Take(100)一起使用.

I do need to add that the code as it stands will still run all 300 URLs, it just will return quicker...thats all. You would need to add the cancelation token to the semaphore.WaitAsync(token) to cancel the queued work. Again I suggest using Rx.Net for that. Its just easier to use Rx.Net to get the cancelation token to work with .Take(100).

这篇关于在ASP.NET中限制异步任务,对N个成功任务的限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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