【发布时间】:2013-01-10 19:05:39
【问题描述】:
我正在尝试加载一个间隔进程队列。换句话说,我有一个队列,我希望队列中的每个项目都以单独的间隔运行。
我的问题是我似乎无法一次运行超过 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 收集计时器,但是我知道什么。
【问题讨论】:
-
为什么要同时运行这么多线程?
-
这是一个轮询服务。它必须以指定的时间间隔轮询 n 个提要。我可以制作一个精美的队列系统并运行 n 个单独的服务,每个服务只轮询 1 个提要。但是,我想做这个元;我希望程序启动每个单独的进程。
-
你的答案还是错的。一切都可能被垃圾收集,排除计时器没什么特别的。您应该保留对所有计时器的引用,然后在完成后将其丢弃。否则,它们仍可能在垃圾收集时被丢弃。
标签: c# .net multithreading