3

我有以下代码:

for (int i = 1; i <= 500; i++)
{
    BackgroundWorker t = new BackgroundWorker();

    t.DoWork += SOME DB METHOD THAT TAKES 5 SECONDS
    t.RunWorkerAsync();
}

当我在 SQL 中对此进行分析时,我注意到BackgroundWorker似乎以这样一种方式对线程进行排队,即同时打开 4 或 5 个活动连接,而同时打开所有 500 个连接。我的数据库没有超时或阻塞。如何防止这种排队并同时使用所有 500 个并发线程访问数据库?

4

3 回答 3

6

BackgroundWorker使用线程池。ThreadPool.SetMinThreads您可以使用和调整线程池ThreadPool.SetMaxThreads。如果实际上有可能建立到您的数据库服务器的那么多连接可能是另一个问题(并导致其他问题)。

但是,不建议启动 500 个BackgroundWorker实例!带有任务类的“任务并行库”可以提供更好的解决方案。

于 2013-07-02T13:45:48.957 回答
1

这样的事情应该会有所帮助:

Task.Factory.StartNew(
    () => { SOME DB METHOD THAT TAKES 5 SECONDS },
    TaskCreationOptions.LongRunning
);

MSDN 文档

LongRunning - 指定任务将是一个长时间运行的粗粒度操作,涉及比细粒度系统更少、更大的组件。它向 TaskScheduler 提供了一个提示,表明可能需要超额订阅。超额订阅允许您创建比可用硬件线程数更多的线程。


或者,您可以完全绕过线程池并直接使用Thread类:

var t = new Thread(() => { SOME DB METHOD THAT TAKES 5 SECONDS });
t.Start();

“原始”线程将比任务更难处理,尽管......

于 2013-07-02T13:48:37.093 回答
0

你没有,因为你的计算机不可能同时运行 500 个线程。最有可能的是,您有 8 到 16 个逻辑线程,当您运行代码时,剩下 4 或 5 个是可用的。似乎100%合法。

于 2013-07-02T13:45:53.940 回答