C# 限制并行运行方法的数量
在我的课堂上,我有一个下载功能。现在为了不允许太多的并发下载,我想阻止这个功能,直到“下载点”是免费的;) 在C#/.NET中是否有现成的编程模式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
编辑:不幸的是,我不能使用.net4.5中的功能,而只能使用.net4.0中的功能。您应该使用信号量对于此并发问题,请参阅文档中的更多内容: 可能是这样
var parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = 3
};
Parallel.ForEach(downloadUri, parallelOptions, (uri, state, index) =>
{
YourDownLoad(uri);
});
对于这种情况,我使用一些方法在自定义类(如
QueryManager
)中创建了自己的队列
:
队列
查询中排队checkIfQueryCouldBeSent()
您必须将回调存储在
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);
}