繁体   English   中英

Windows Server 2003的BackgroundWorker限制

[英]BackgroundWorker limitation on Windows server 2003

我目前在Windows Server 2003上运行BackgroundWorker遇到问题。我有一个窗口应用程序,需要运行50个以上的threads

我编写的代码使用BackgroundWorker (BW)作为线程包装器将数据更新到窗口表单上。 问题是该代码能够在我的XP机器上运行超过50次BW,但在Windows 2003服务器上运行时却停止在50次。

起初,我对每个应用程序可以运行的线程数量有所限制。 谷歌搜索问题表明情况并非如此。 我编写了以下代码来确认这一点。

static int count = 0;

static void Main(string[] args)
{
    int max = 55; // default value

    if (args.Length > 0)
            // use command line parameter if provided
        max = Convert.ToInt32(args[0]); 

    List<Thread> threadList = new List<Thread>();
    try
    {
        while (count < max)
        {
            Thread newThread = new Thread(
                        new ParameterizedThreadStart(DummyCall), 1024);
            newThread.Start(count);

            threadList.Add(newThread);
            count++;
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }

    Console.ReadLine();
}

static void DummyCall(object obj)
{
    Console.WriteLine(obj.ToString());
    Thread.Sleep(1000000000);
}

结果显示出预期的效果。 我可以在XP机器和2003服务器上看到从0到54的数字列表。

但是,当我尝试使用BW时,我的XP计算机运行到54,而2003服务器运行到49(50 BW)。 这是代码。

static int count = 0;

static void Main(string[] args)
{
    int max = 55; // default value

    if (args.Length > 0)
            // use command line parameter if provided
        max = Convert.ToInt32(args[0]); 

    List<BackgroundWorker> list = new List<BackgroundWorker>();

    try
    {
        while (count < max)
        {
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            worker.RunWorkerAsync(count);

            list.Add(worker);

            count++;
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }

    Console.ReadLine();
}

static void worker_DoWork(object sender, DoWorkEventArgs e)
{
    Console.WriteLine(e.Argument.ToString());
    Thread.Sleep(1000000000);
}

因此,问题在于,为什么在2003服务器上可以运行但不能在XP上运行的BW实例数量受到限制? 无论如何,我可以增加2003服务器上BW实例的数量吗? 如果是,我该怎么做?

BackgroundWorker对于您正在执行的工作是不适当的选择-它旨在作为一种手段(在保持UI响应能力的同时)剥离(通常是单个)工作线程。 为工作线程提供了与UI交互的简便方法-我怀疑您有50个线程都在与UI接触。

考虑直接使用线程。 ThreadPool使这变得容易。 从MSDN:

using System;
using System.Threading;
public class Example {
    public static void Main() {
        // Queue the task.
        ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));

        Console.WriteLine("Main thread does some work, then sleeps.");
        Thread.Sleep(1000);

        Console.WriteLine("Main thread exits.");
    }

    // This thread procedure performs the task.
    static void ThreadProc(Object stateInfo) {
        // No state object was passed to QueueUserWorkItem, so 
        // stateInfo is null.
        Console.WriteLine("Hello from the thread pool.");
    }
}

您看到50个线程的限制,因为某些版本的CLR的默认限制是每个内核25个ThreadPool线程。 因此,在双核CPU上,有50个线程。 您可以使用ThreadPool.SetMaxThreads增强它。 我相信较新的CLR版本会将默认值设置得更高。 还要注意,ThreadPool将线程的创建速度限制为每500ms一个新线程。

您的两个系统运行的框架版本完全相同(包括SP)吗? 它们具有相同数量的核心吗?

请注意,线程具有相当大的开销,因此创建比核心多得多的线程通常不值得。 如果瓶颈在CPU之外(例如,您正在与多个远程系统通信),那么拥有数十个线程可能是值得的。 如果您正在执行CPU限制的计算,则不是。 如果您的磁盘受到IO的限制,请注意不要因该数量的并行操作而影响磁盘。

正如Michael Petrotta所说, BackgroundWorker实际上仅用于单个工作线程,以使您的UI保持响应。

如果您有很多短期操作,但实际上并不想运行许多长期操作,则ThreadPool很有用。 默认的最大线程数取决于CLR版本(从2.0 SP1开始每个CPU 250个,之前每个CPU 25个)。 您可以使用ThreadPool.SetMaxThreads增加此数字,但我不建议这样做。

如果您有50多个需要并行执行的长期CPU限制动作,我认为最好的选择是为每个动作创建一个线程并使用AsyncOperationSynchronizationContext )更新您的UI。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM