我正在尝试加载一个间隔进程队列。换句话说,我有一个队列,我希望队列中的每个项目都以单独的间隔运行。
我的问题是我似乎一次无法运行超过 25 个线程。我在 64 位机器上使用 .Net 4.5,它的默认最大线程数为 32768。
如何让我的应用程序运行我的机器可以处理的尽可能多的并发线程?
这是一个示例应用程序,它在我的生产代码中复制了实际问题:
class Program
{
static void Main(string[] args)
{
System.Threading.ThreadPool.SetMaxThreads(200, 200);
test t = new test();
t.LoadUrls("http://www.google.com");
while (1 == 1)
{
System.Threading.Thread.Sleep(1000);//refresh every 5 seconds
Console.WriteLine(System.Diagnostics.Process.GetCurrentProcess().Threads.Count);
}
}
public class test
{
public void LoadUrls(string url)
{
for (int i = 0; i < 100; i++)
{
System.Threading.Timer t = new System.Threading.Timer(new System.Threading.TimerCallback(RunInterval), url, 0, 1000);
Console.WriteLine("Loaded {0} feeds.", i);
}
}
private static void RunInterval(object state)
{
string url = state as string;
string data = "";
using (System.Net.WebClient cl = new System.Net.WebClient())
{
Console.WriteLine("getting data for " + url);
data = cl.DownloadString(url);
}
//do something with the data
}
}
}
这段代码理论上应该在 2 秒左右后运行 198 个线程。
顺便说一句,这在我的原型应用程序中运行良好;它是用节点写的。但是,现在我无法让它在 c# 中正常工作......
回答: 问题实际上是垃圾收集,根本不是线程池问题。池完全能够假脱我扔给它的所有线程。诀窍是使用 System.Threading.Timer 的单参数构造函数;这将使计时器将自身用作信号量,从而避免 gc。
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
test t = new test();
t.url = "http://www.google.com?" + i;
System.Threading.Timer ti = new System.Threading.Timer(new System.Threading.TimerCallback(t.RunInterval));
ti.Change(0, 1000);
}
while (1 == 1)
System.Threading.Thread.Sleep(int.MaxValue);
}
public class test
{
public string url { get; set; }
public void RunInterval(object state)
{
Console.WriteLine("getting data for " + this.url);
string data = "";
using (System.Net.WebClient cl = new System.Net.WebClient())
{
data = cl.DownloadString(this.url);
}
}
}
}
我不确定您为什么希望 gc 收集计时器,但是我知道什么。