7

間隔プロセスのキューをロードしようとしています。つまり、キューがあり、キュー内の各アイテムを個別の間隔で実行したいということです。

私の問題は、一度に 25 を超えるスレッドを実行できないように見えることです。デフォルトの最大スレッド数が 32768 の 64 ビット マシンで .Net 4.5 を使用しています。

マシンが処理できる数の同時スレッドをアプリで実行するにはどうすればよいですか?

私の製品コードで実際の問題を再現するアプリの例を次に示します。

class Program
{
    static void Main(string[] args)
    {
        System.Threading.ThreadPool.SetMaxThreads(200, 200);
        test t = new test();

        t.LoadUrls("http://www.google.com");

        while (1 == 1)
        {
            System.Threading.Thread.Sleep(1000);//refresh every 5 seconds
            Console.WriteLine(System.Diagnostics.Process.GetCurrentProcess().Threads.Count);
        }
    }


    public class test
    {

        public void LoadUrls(string url)
        {
            for (int i = 0; i < 100; i++)
            {
                System.Threading.Timer t = new System.Threading.Timer(new System.Threading.TimerCallback(RunInterval), url, 0, 1000);
                Console.WriteLine("Loaded {0} feeds.", i);
            }
        }
        private static void RunInterval(object state)
        {
            string url = state as string;
            string data = "";

            using (System.Net.WebClient cl = new System.Net.WebClient())
            {
                Console.WriteLine("getting data for " + url);
                data = cl.DownloadString(url);
            }

            //do something with the data

        }
    }
}

このコードは、理論的には 2 秒程度で 198 スレッドを実行するはずです。

ところで、これは私のプロトタイプ アプリで見事に機能しました。ノードに書いてありました。しかし、今ではC#で正しく動作させることができません...

回答: 問題は実際にはガベージ コレクションにあり、スレッドプールの問題ではありませんでした。プールは、私が投げているすべてのスレッドをスプールする以上の能力があります。その秘訣は、System.Threading.Timer の単一パラメーター コンストラクターを使用することです。これにより、タイマーはそれ自体をセマフォとして使用するようになり、gc が回避されます。

class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 100; i++)
        {
            test t = new test();
            t.url = "http://www.google.com?" + i;
            System.Threading.Timer ti = new System.Threading.Timer(new System.Threading.TimerCallback(t.RunInterval));
            ti.Change(0, 1000);
        }

        while (1 == 1)
            System.Threading.Thread.Sleep(int.MaxValue);
    }


    public class test
    {
        public string url { get; set; }
        public void RunInterval(object state)
        {
            Console.WriteLine("getting data for " + this.url);
            string data = "";

            using (System.Net.WebClient cl = new System.Net.WebClient())
            {
                data = cl.DownloadString(this.url);
            }
        }
    }
}

gc によってタイマーを収集する必要がある理由はわかりませんが、私は何を知っていますか。

4

3 に答える 3

5

マシンが処理できる数の同時スレッドをアプリで実行するにはどうすればよいですか?

それは間違ったアプローチです。すべてのスレッドはコストがかかり、数百を作成すると、システムが大幅に劣化します。

コードはThreadPoolを使用しています。プールには、スレッドの数を制限するアルゴリズムがあります。Sleep()時間を増やすと、さらにいくつかのスレッドが表示される場合があります。

より直接的な方法は、ThreadPool.MinThreadsを設定することです。ただし、パフォーマンスは向上するのではなく、低下することを期待してください。

于 2013-01-10T19:08:29.487 に答える
3

System.Threading.Timerによると

Use a TimerCallback delegate to specify the method you want the Timer to execute. The timer delegate is specified when the timer is constructed, and cannot be changed. The method does not execute on the thread that created the timer; it executes on a ThreadPool thread supplied by the system.

次にSystem.Threading.Threadpoolで

There is one thread pool per process. Beginning with the .NET Framework 4, the default size of the thread pool for a process depends on several factors, such as the size of the virtual address space. A process can call the GetMaxThreads method to determine the number of threads. The number of threads in the thread pool can be changed by using the SetMaxThreads method. Each thread uses the default stack size and runs at the default priority.

于 2013-01-10T19:15:47.527 に答える
1

MaxDegreeOfParallelism というプロパティを使用したいのですが、コードを少し変更する必要があります。次に、それをテストして、並行して実行するスレッドの最適な数を見つけます。ここにリンクがあります:http://msdn.microsoft.com/en-us/library/system.threading.tasks.paralleloptions.maxdegreeofparallelism.aspx

于 2013-01-10T19:12:04.077 に答える