C# 限制并行运行方法的数量

C# 限制并行运行方法的数量,c#,.net,.net-4.0,C#,.net,.net 4.0,在我的课堂上,我有一个下载功能。现在为了不允许太多的并发下载,我想阻止这个功能,直到“下载点”是免费的;) 在C#/.NET中是否有现成的编程模式 编辑:不幸的是,我不能使用.net4.5中的功能,而只能使用.net4.0中的功能。您应该使用信号量对于此并发问题,请参阅文档中的更多内容: 可能是这样 var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = 3 }; Parallel.For

在我的课堂上,我有一个下载功能。现在为了不允许太多的并发下载,我想阻止这个功能,直到“下载点”是免费的;)

在C#/.NET中是否有现成的编程模式


编辑:不幸的是,我不能使用.net4.5中的功能,而只能使用.net4.0中的功能。您应该使用信号量对于此并发问题,请参阅文档中的更多内容: 可能是这样

var parallelOptions = new ParallelOptions
{        
    MaxDegreeOfParallelism = 3
};

Parallel.ForEach(downloadUri, parallelOptions, (uri, state, index) =>
{
    YourDownLoad(uri);
});

对于这种情况,我使用一些方法在自定义类(如
QueryManager
)中创建了自己的
队列

  • 每个新查询都在
    队列
    查询中排队
  • 在每次“排队”和每次查询回答之后,我调用
    checkIfQueryCouldBeSent()
  • 方法检查您的条件:伴随查询的数量,等等。在您的情况下,如果全局计数器小于5,则接受启动新查询。然后你增加计数器
  • 减少查询答案中的计数器
  • 只有当所有查询都是异步的时,它才起作用。
    您必须将回调存储在
    MyQuery
    类中,并在查询结束时调用它。

    您正在执行异步IO绑定的工作,不需要使用多个线程进行调用,例如
    Parallel.ForEach

    您可以简单地使用BCL中公开的自然异步API,例如使用
    HttpClient
    进行HTTP调用的API。然后,您可以使用
    SemaphoreSlim
    和异步等待的
    WaitAsync
    方法来限制连接:

    private readonly SemaphoreSlim semaphoreSlim = new SemaphoreSlim(3);
    public async Task DownloadAsync(Uri uri)
    {
        await semaphoreSlim.WaitAsync();
        try
        {
            string result = await DoActualDownloadAsync(uri);
        }
        finally
        {
            semaphoreSlim.Release();
        }
    }
    
    您的
    doactualydownloadsync
    将使用
    HttpClient
    来完成它的工作。大致如下:

    public Task<string> DoActualDownloadAsync(Uri uri)
    {
        var httpClient = new HttpClient();
        return httpClient.GetStringAsync(uri);
    }
    
    public任务doactualdownloadsync(Uri)
    {
    var httpClient=新的httpClient();
    返回httpClient.GetStringAsync(uri);
    }
    
    静态变量,用于跟踪当前下载的数量并确保线程安全。我看不到任何并行代码。如果不显示实际代码,就无法提供帮助。有一些构造会有所帮助,但它们取决于用于执行异步操作的API。例如,PLINQ和数据流具有MaxDegreeOfParallelism选项。Task.Run可以与TaskScheduler结合使用,TaskScheduler只允许一定数量的并发任务。我假设
    下载
    是IO绑定操作?@YuvalItzchakov它通过http下载一个文件,然后将其写入磁盘。所以是的。@PanagiotisKanavos这个方法可以从这个类的许多实例中调用。NET框架已经包含了这样一个类,带有MaxDegreeOfParallelismoption@PanagiotisKanavos感谢您提供的信息,我阅读了ActionBlock规范。然而,我认为它不适合异步操作,异步操作必须能够通知ActionBlock继续执行下一个操作。在异步操作的情况下,整个ActionBlock似乎会立即完成。ActionBlock是专为异步处理而构建的,它是Robotics框架的后代。如果您的方法返回任务,您可以在块委托中等待,也可以返回任务本身。有一个ActionBlock构造函数处理返回任务的函数。您还可以通过调用
    block.Complete()来等待ActionBlock完成处理;等待区块完成
    ;谢谢这听起来很有趣!但在我的例子中,我想确保调用YourDownload的人只在调用实际完成后才继续。
    public Task<string> DoActualDownloadAsync(Uri uri)
    {
        var httpClient = new HttpClient();
        return httpClient.GetStringAsync(uri);
    }