gpt4 book ai didi

c# - 多个 Web 请求的最佳多线程方法

转载 作者:太空狗 更新时间:2023-10-30 00:19:55 25 4
gpt4 key购买 nike

我想创建一个程序来抓取和检查我的网站是否存在 http 错误和其他问题。我想用多个线程来执行此操作,这些线程应该接受要抓取的 url 之类的参数。尽管我希望 X 个线程处于事件状态,但仍有 Y 个任务已在等待执行。

现在我想知道执行此操作的最佳策略是什么:ThreadPool、Tasks、Threads 还是其他?

最佳答案

这是一个示例,展示了如何将一堆任务排队但限制并发运行的数量。它使用 Queue 来跟踪准备运行的任务,并使用 Dictionary 来跟踪正在运行的任务。当任务完成时,它会调用回调方法将自己从 Dictionary 中删除。 async 方法用于在空间可用时启动排队的任务。

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace MinimalTaskDemo
{
class Program
{
private static readonly Queue<Task> WaitingTasks = new Queue<Task>();
private static readonly Dictionary<int, Task> RunningTasks = new Dictionary<int, Task>();
public static int MaxRunningTasks = 100; // vary this to dynamically throttle launching new tasks

static void Main(string[] args)
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
Worker.Done = new Worker.DoneDelegate(WorkerDone);
for (int i = 0; i < 1000; i++) // queue some tasks
{
// task state (i) will be our key for RunningTasks
WaitingTasks.Enqueue(new Task(id => new Worker().DoWork((int)id, token), i, token));
}
LaunchTasks();
Console.ReadKey();
if (RunningTasks.Count > 0)
{
lock (WaitingTasks) WaitingTasks.Clear();
tokenSource.Cancel();
Console.ReadKey();
}
}

static async void LaunchTasks()
{
// keep checking until we're done
while ((WaitingTasks.Count > 0) || (RunningTasks.Count > 0))
{
// launch tasks when there's room
while ((WaitingTasks.Count > 0) && (RunningTasks.Count < MaxRunningTasks))
{
Task task = WaitingTasks.Dequeue();
lock (RunningTasks) RunningTasks.Add((int)task.AsyncState, task);
task.Start();
}
UpdateConsole();
await Task.Delay(300); // wait before checking again
}
UpdateConsole(); // all done
}

static void UpdateConsole()
{
Console.Write(string.Format("\rwaiting: {0,3:##0} running: {1,3:##0} ", WaitingTasks.Count, RunningTasks.Count));
}

// callback from finished worker
static void WorkerDone(int id)
{
lock (RunningTasks) RunningTasks.Remove(id);
}
}

internal class Worker
{
public delegate void DoneDelegate(int taskId);
public static DoneDelegate Done { private get; set; }
private static readonly Random Rnd = new Random();

public async void DoWork(object id, CancellationToken token)
{
for (int i = 0; i < Rnd.Next(20); i++)
{
if (token.IsCancellationRequested) break;
await Task.Delay(100); // simulate work
}
Done((int)id);
}
}
}

关于c# - 多个 Web 请求的最佳多线程方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15706158/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com