簡體   English   中英

C#多個任務不能並行運行

[英]c# multiple tasks do not run in parallel

我試圖創建一個多線程骰子滾動模擬-只是出於好奇心,多線程編程的樂趣,並向其他人展示“隨機結果”的效果(許多人不明白,如果您連續六次滾動拉普拉斯骰子,您已經有1、2、3、4、5,則下一卷不是6.)。 為了向他們展示n個骰子與m個骰子的分布,我創建了此代碼。

好吧,即使我為程序運行的單線程的每個骰子創建一個新任務,結果也不錯。 隨着完成時間的快速增長,多線程模擬6個或更多骰子的“成千上萬”的重新滾動是合理的。

我從msdn閱讀了幾個示例,所有示例都表明應該同時運行多個任務。 有人可以給我一個提示,為什么這段代碼沒有利用很多線程/內核嗎? (甚至,當我嘗試一次運行400個骰子並重新滾動1000萬次時)

首先,我初始化存儲結果的鋸齒狀數組。 第一維:每個骰子1個條目,第二維是每個骰子滾動的眼睛分布。

接下來,我創建一個任務數組,每個任務返回一個結果數組(如上所述,第二個維度)。每個數組都有6個條目,分別代表拉普拉斯W6骰子的每一面。 如果骰子擲出一只眼睛,則第一項[0]增加+1。 因此,您可以直觀地看到每個值的滾動頻率。

然后,我使用一個普通的for循環啟動所有線程。 沒有指示等待線程,直到所有線程都啟動。

最后,我等待所有人完成並總結結果。 更改沒有任何區別

Task.WaitAll(任務); 到Task.WhenAll(tasks);

再說一次我的話:為什么這些代碼不占用我CPU的多個核心? 我必須改變什么?

提前致謝!

這是代碼:

private void buttonStart_Click(object sender, RoutedEventArgs e)
    {      
        int tries = 1000000;
        int numberofdice = 20   ;
        int numberofsides = 6; // W6 = 6
        var rnd = new Random();

        int[][] StoreResult = new int[numberofdice][];
        for (int i = 0; i < numberofdice; i++)
        {
            StoreResult[i] = new int[numberofsides];
        }

        Task<int[]>[] tasks = new Task<int[]>[numberofdice];


        for (int ctr = 0; ctr < numberofdice; ctr++)
        {

            tasks[ctr] = Task.Run(() =>
            {
                int newValue = 0;
                int[] StoreTemp = new int[numberofsides]; // Array that represents how often each value appeared
                for (int i = 1; i <= tries; i++) // how often to roll the dice
                {
                    newValue = rnd.Next(1, numberofsides + 1); // Roll the dice; UpperLimit for random int EXCLUDED from range 
                    StoreTemp[newValue-1] = StoreTemp[newValue-1] + 1; //increases value corresponding to eyes on dice by +1
                }
                return StoreTemp;
            });
                StoreResult[ctr] = tasks[ctr].Result; // Summing up the individual results for each dice in an array

        }
        Task.WaitAll(tasks);

          // do something to visualize the results - not important for the question

        }
    }

這里的問題是tasks[ctr].Result .Result部分本身會等待函數完成,然后再將結果int數組存儲到StoreResult中。 而是在Task.WaitAll之后創建一個新循環以獲取結果。

您可以考慮執行Parallel.Foreach循環,而不是為此手動創建單獨的任務。

正如其他人指出的那樣,當您嘗試進行匯總時,您最終只能等待每個任務完成,因此實際上並不是多線程的。

非常重要的注意事項: C#隨機數生成器不是線程安全的 (有關此主題的討論,另請參見此MSDN博客文章 )。 不要在多個線程之間共享同一實例。 文檔中

...隨機對象不是線程安全的。 如果您的應用從多個線程調用隨機方法,則必須使用同步對象來確保一次只有一個線程可以訪問隨機數生成器。 如果不確保以線程安全的方式訪問Random對象,則對返回隨機數的方法的調用將返回0。

而且,只是挑剔,使用Task與進行多線程並不是一回事。 實際上,盡管您在這里進行多線程處理,但也可以使用async / await來執行純異步,非多線程代碼。 這主要用於I / O綁定操作,在該操作中創建一個單獨的線程只是為了等待結果是沒有意義的(但最好是允許調用線程在等待結果的同時做其他工作)。

我認為您在分配給主數組時不必擔心線程安全(假設每個線程僅分配給數組中的特定索引,而沒有其他人分配給相同的內存位置); 您只需要擔心在多個線程同時訪問/修改共享可變狀態時進行鎖定。 如果我正確閱讀此文件,則該狀態可變狀態(但不是共享的可變狀態)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM