Wer*_*lve 5 c# multithreading limit threadpool
我有一个列表,其中包含我要下载的项目.我使用for循环来迭代列表.
对于此List中的每个项目,我启动一个引用该项目的新线程.我的问题是我想要同时限制maxDownload.
for (int i = downloadList.Count - 1; i >= 0; i--)
{
downloadItem item = downloadList[i];
if (item.Status != 1 && item.Status != 2)
{
ThreadStart starter = delegate { this.DownloadItem(ref item); };
Thread t = new Thread(starter);
t.IsBackground = true;
t.Name = item.Name;
t.Priority = ThreadPriority.Normal;
t.Start();
}
}
Run Code Online (Sandbox Code Playgroud)
我读了一些关于ThreadPool的内容,但后来我无法引用我的项目.有人能帮我吗?谢谢!:)
我测试了这个:
ThreadPool.SetMaxThreads(maxDownloads, maxDownloads);
ThreadPool.SetMinThreads(maxDownloads, maxDownloads);
ThreadPool.QueueUserWorkItem(DownloadItem, ref item);
Run Code Online (Sandbox Code Playgroud)
我不知道如何用这个帖子引用我的downloadItem .....
如果你使用的是.NET 4,我强烈建议使用Parallel.ForEach(可能在downloadList.Reverse()上)
所以,像:
Parallel.ForEach(downloadList.Reverse(),
new ParallelOptions { MaxDegreeOfParallelism = 8 },
item => this.DownloadItem(item));
Run Code Online (Sandbox Code Playgroud)
如果你不想阻塞调用线程,你当然可以使用QueueUserWorkItem这个调用.
我通过创建线程并将它们加载到队列中解决了.Net 3.5中的这个问题.然后我从队列中读取一个线程,启动它,并增加正在运行的线程数.我一直这样做,直到达到上限.
当每个线程完成时,它会调用一个回调方法,该方法减少运行计数并通知队列读取器启动更多线程.对于其他控制,您可以使用字典来跟踪正在运行的线程ManagedThreadId,因此您可以发出线程提前停止或报告进度的信号.
示例控制台应用:
using System;
using System.Collections.Generic;
using System.Threading;
namespace ThreadTest
{
class Program
{
static void Main(string[] args)
{
Supervisor supervisor = new Supervisor();
supervisor.LaunchThreads();
Console.ReadLine();
supervisor.KillActiveThreads();
Console.ReadLine();
}
public delegate void WorkerCallbackDelegate(int threadIdArg);
public static object locker = new object();
class Supervisor
{
Queue<Thread> pendingThreads = new Queue<Thread>();
Dictionary<int, Worker> activeWorkers = new Dictionary<int, Worker>();
public void LaunchThreads()
{
for (int i = 0; i < 20; i++)
{
Worker worker = new Worker();
worker.DoneCallBack = new WorkerCallbackDelegate(WorkerCallback);
Thread thread = new Thread(worker.DoWork);
thread.IsBackground = true;
thread.Start();
lock (locker)
{
activeWorkers.Add(thread.ManagedThreadId, worker);
}
}
}
public void KillActiveThreads()
{
lock (locker)
{
foreach (Worker worker in activeWorkers.Values)
{
worker.StopWork();
}
}
}
public void WorkerCallback(int threadIdArg)
{
lock (locker)
{
activeWorkers.Remove(threadIdArg);
if (activeWorkers.Count == 0)
{
Console.WriteLine("no more active threads");
}
}
}
}
class Worker
{
public WorkerCallbackDelegate DoneCallBack { get; set; }
volatile bool quitEarly;
public void DoWork()
{
quitEarly = false;
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + " started");
DateTime startTime = DateTime.Now;
while (!quitEarly && ((DateTime.Now - startTime).TotalSeconds < new Random().Next(1, 10)))
{
Thread.Sleep(1000);
}
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + " stopped");
DoneCallBack(Thread.CurrentThread.ManagedThreadId);
}
public void StopWork()
{
quitEarly = true;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)