簡體   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