我正在尝试加载一个间隔进程的队列。换句话说,我有一个队列,希望队列中的每个项在单独的时间间隔上运行。
我的问题是,我似乎无法同时运行超过25个线程。我使用的是.NET 4.5,在一台默认最大线程数为32768的64位机器上。
如何使我的应用程序运行尽可能多的并发线程?
这里有一个示例应用程序,可以复制我生产代码中的实际问题:
这段代码理论上应该在大约2秒后运行198个线程。
顺便说一下,在我的原型应用程序中,这个代码完美地工作了;它是使用node编写的。但是,现在我无法在c#中正确地运行它...
答案: 问题实际上是垃圾回收造成的,而不是线程池问题;线程池足以处理我投入其中的所有线程。关键是要使用System.Threading.Timer的单参数构造函数;这会使计时器将自己用作信号量,从而避免 gc。
我的问题是,我似乎无法同时运行超过25个线程。我使用的是.NET 4.5,在一台默认最大线程数为32768的64位机器上。
如何使我的应用程序运行尽可能多的并发线程?
这里有一个示例应用程序,可以复制我生产代码中的实际问题:
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个线程。
顺便说一下,在我的原型应用程序中,这个代码完美地工作了;它是使用node编写的。但是,现在我无法在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);
}
}
}
}
我不确定为什么你会希望计时器被垃圾回收收集,但是嘿,我也不知道。