一、消费者线程输出特别慢
老旧的代码,现在需要加一些新玩意,为此还给他换了一台机器。老旧的代码摇摇欲坠,小心翼翼的维护,每改一行都担心受怕,就像头上悬了一把刀。老代码中有一些数据,现在需要发送给总控,所以我需要添加一个TcpServer,感觉这个不是很难。大概就是开几个线程,一个发状态,一个发数据A,一个发数据B。
问题来了,当我加上网络的初始化之后,老代码中有一个数据在刚打开时往界面加载变慢了许多,如果不初始化我的网络模块就没问题。我陷入了沉思,根本找不到原因。
二、问题的所在
很久很久以后,就连客户都要放弃的时候,有一个午夜,我进行了一次尝试。主线程中,先打开生产者线程,然后打开消费者线程,生产者线程将数据推入缓冲区,消费者线程开始取。
//主线程
//---记录此刻时间A;
System.Threading.Task.Factory.StartNew(()=>{
//---记录此刻时间B;
//开始生产数据……填入缓冲区
});
System.Threading.Task.Factory.StartNew(()=>{
//---记录此刻时间C;
//从缓冲区读数据……往界面推数据
});
我加上了记录三个时间节点A、B、C的代码,发现在最坏的情况下BC的时间比A晚了四五秒。
为什么去掉网络的初始化就好了?
我打开了线程界面,发现初始化网络之后线程数从15左右增加到了40左右;我意识到了问题的所在,难道Task有问题?
三、查找资料
我去网上找,为什么Task没有立即启动!没什么人回答,毕竟CSharper还是太少,在混乱的网络里还是有一些蛛丝马迹被我发现了。有人提到Task用的是ThreadPool,而线程池是有数量限制的,数量超过之后会有问题。
四、写代码验证
ThreadPool.GetMinThreads(out minWorkers,out minIOC);可以获取当前最小线程保持活跃数,也就是说即是没有线程也会保持minWorker个线程,这样在需要大量创建线程的时候就不会耗费太久的时间。
这台机器默认的值是8,ThreadPool.SetMinThreads(50, 50)可以进行设置,设置之后果然好了许多,还待进一步观察。
int minWorkers, minIOC;
int maxWorkers, maxIOC;
ThreadPool.GetMinThreads(out minWorkers,out minIOC);
Console.WriteLine(minWorkers+"-min-"+minIOC);
ThreadPool.GetMaxThreads(out maxWorkers, out maxIOC);
Console.WriteLine(maxWorkers + "-max-" + maxIOC);
if (!ThreadPool.SetMinThreads(50, 50))
{
Console.WriteLine("设置失败!");
}
接着使用两种方法进行测试,一个使用Task开线程,一个使用Thread开线程。使用Task的前minWorkers线程时间差不多,但是之后的就开始耗时起来了,平均一个0.5到1秒不等。使用Thread的没有这个问题,会不会有别的问题呢?我还不知道!
string rootPaht = Environment.CurrentDirectory;
//使用Task.Factory.start开启线程
System.IO.Directory.CreateDirectory(rootPaht + "/abcdefg");
for (int i = 0; i < 20; i++)
{
System.Threading.Tasks.Task.Factory.StartNew(() =>{
int j = 1000;
while (j-->0)
{
string s = Thread.CurrentThread.ManagedThreadId.ToString() +"--"+ Thread.CurrentThread.Name
+ "\t----------" + DateTime.Now.ToString("hhmmss:fff");
string path = rootPaht+"/abcdefg/" + Thread.CurrentThread.ManagedThreadId.ToString()+".txt";
System.IO.File.AppendAllLines(path, new string[] { s });
Thread.Sleep(30);
}
});
}
//使用Thread开启线程
System.IO.Directory.CreateDirectory(rootPaht + "/hijklmn");
for (int i = 0; i < 20; i++)
{
new Thread(()=> {
int j = 1000;
while (j-- > 0)
{
string s = Thread.CurrentThread.ManagedThreadId.ToString() + "--" + Thread.CurrentThread.Name
+ "\t----------" + DateTime.Now.ToString("hhmmss:fff");
string path = rootPaht + "/hijklmn/" + Thread.CurrentThread.ManagedThreadId.ToString() + ".txt";
System.IO.File.AppendAllLines(path, new string[] { s });
Thread.Sleep(30);
}
}).Start();
}
五、修改
测试之后,我在老代码上加上了ThreadPool.SetMinThreads(50, 50),情况好转了许多。暂时算是还可以,看看之后在哪里翻车吧!对了,老代码用的是VS2010+.NETFramework4.0,比较古老了!
可是为什么网络模块新建了那么多线程呢,我是不是要换一个库了!不过最近的库都不支持4.0了,升级代码版本也是很头疼!