C# 保持异步运行特定数量的任务
我目前正在开发一个并发文件下载程序 出于这个原因,我想参数化并发任务的数量。我不想等待所有的任务都完成,但要保持相同的数字正在运行 事实上,star overflow上的这个线程给了我一个正确的线索,但我正在努力使它异步: 这是我的密码:C# 保持异步运行特定数量的任务,c#,.net,asynchronous,concurrency,task,C#,.net,Asynchronous,Concurrency,Task,我目前正在开发一个并发文件下载程序 出于这个原因,我想参数化并发任务的数量。我不想等待所有的任务都完成,但要保持相同的数字正在运行 事实上,star overflow上的这个线程给了我一个正确的线索,但我正在努力使它异步: 这是我的密码: public async Task StartAsync() { var semaphore = new SemaphoreSlim(1, _concurrentTransfers); var queueHasMessa
public async Task StartAsync()
{
var semaphore = new SemaphoreSlim(1, _concurrentTransfers);
var queueHasMessages = true;
while (queueHasMessages)
{
try {
await Task.Run(async () =>
{
await semaphore.WaitAsync();
await asyncStuff();
});
}
finally {
semaphore.Release();
};
}
}
但是代码一次只执行一个。我认为wait正在阻止我生成所需数量的任务,但我不知道如何避免它,同时遵守信号量建立的限制
如果我将所有任务添加到一个列表中并创建一个whenall,信号量会抛出一个异常,因为它已达到最大计数
有什么建议吗 我注意到,直通解决方案将删除执行期间发生的任何异常。那太糟糕了 以下是一个不会删除异常的解决方案: Run是创建任务的工厂方法。您可以使用intellisense返回值检查自己。您可以将返回的任务分配到任意位置 wait是一个操作符,它将等待它所操作的任务完成。您可以使用wait操作符执行任何任务
public static async Task RunTasksConcurrently()
{
IList<Task> tasks = new List<Task>();
for (int i = 1; i < 4; i++)
{
tasks.Add(RunNextTask());
}
foreach (var task in tasks) {
await task;
}
}
public static async Task RunNextTask()
{
while(true) {
await Task.Delay(500);
}
}
您可以使用老式的方法轻松地完成这项工作,而无需使用wait by use,它允许您指定要使用的最大并发线程数 例如:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
public static void Main(string[] args)
{
IEnumerable<string> filenames = Enumerable.Range(1, 100).Select(x => x.ToString());
Parallel.ForEach(
filenames,
new ParallelOptions { MaxDegreeOfParallelism = 4},
download
);
}
static void download(string filepath)
{
Console.WriteLine("Downloading " + filepath);
Thread.Sleep(1000); // Simulate downloading time.
Console.WriteLine("Downloaded " + filepath);
}
}
}
尝试一下,看看输出中的差异
然而,如果您想要一种更现代的方法来实现这一点,您可以研究-这在异步方法中很有效
这要复杂得多,但要强大得多。你可以用一个例子来做,但是描述如何做超出了我在这里给出的答案的范围
看一看,;它给出了一个简单的例子
还要注意的是,TPL不是内置在.Net中的-您必须从NuGet获得它。您好!谢谢你的回答。我的问题是如何不断地同时运行N个任务。在您的示例中,我希望运行1,2,3,例如,如果完成3次,则同时运行1,2,4。不做那批taks@AdrianAbreu看看我的编辑是否更接近你想要的。这个解决方案太棒了!我喜欢它的简单。我现在正在努力完成递归循环,但它工作得很顺利@AdrianAbreu为什么您发现递归解决方案比在所有条件{await DoWork;}下编写更简单?当然,您可以编写任何循环,但它不会添加任何内容。whiletrue{wait DoWork;}会在DoWork工作时阻止正在运行的任务。他希望同时运行x个任务,而不是按顺序运行。或者,检查中的自定义任务计划程序。它提供了并发限制,您可以在执行已经开始后向计划程序添加其他任务。您应该将Try&Finally放在正在创建的任务中。由于您在finally中释放信号量,它与wait不一致。
RunNextTask(DataObject object)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
public static void Main(string[] args)
{
IEnumerable<string> filenames = Enumerable.Range(1, 100).Select(x => x.ToString());
Parallel.ForEach(
filenames,
new ParallelOptions { MaxDegreeOfParallelism = 4},
download
);
}
static void download(string filepath)
{
Console.WriteLine("Downloading " + filepath);
Thread.Sleep(1000); // Simulate downloading time.
Console.WriteLine("Downloaded " + filepath);
}
}
}
static Random rng = new Random();
static void download(string filepath)
{
Console.WriteLine("Downloading " + filepath);
Thread.Sleep(500 + rng.Next(1000)); // Simulate random downloading time.
Console.WriteLine("Downloaded " + filepath);
}