【发布时间】:2014-07-03 16:26:10
【问题描述】:
在线程计时器回调中调用 PLINQ 的 ForAll 扩展时遇到问题。这将无限期地创建线程。代码示例是实际问题的简单精简版。
class Program
{
static List<int> x = new List<int>();
static void Main(string[] args)
{
x = Enumerable.Range(0, 9).ToList();
System.Threading.Timer[] timers = new System.Threading.Timer[10];
for (int i = 0; i < 10; i++)
timers[i] = new System.Threading.Timer(ElapsedCallback, null, 1000, 1000);
Console.ReadLine();
}
static void ElapsedCallback(object state)
{
int id = Thread.CurrentThread.ManagedThreadId;
x.AsParallel().ForAll(y => Console.WriteLine(y + " - " + Thread.CurrentThread.ManagedThreadId + " - " + id));
}
}
如果在任务管理器中进行监控,可以看到线程计数会增加,直到进程挂起。如果我限制 ThreadPool 大小,进程将创建线程直到该大小,然后也会卡住。
如果在其他代码中也看到该模式。例如,Firebird ADO.Net Provider 中的 ConnectionPool 也以这种方式清理未使用的连接。如果我在这里做一些愚蠢的事情,我不是唯一一个;)有什么见解吗?
编辑:Jim 询问了一些上下文,所以 ...
此模式用于只读事务的事务池中。该应用程序可能在十几个不同的数据库中打开了多个只读事务。每个数据库都有自己的事务池和自己的计时器,该计时器定期提交和处置池中该数据库的旧事务。然后通过 PLINQ 的 ForAll 并行化每个事务提交。
【问题讨论】:
标签: c# multithreading timer plinq