簡體   English   中英

如何等待線程完成而不阻塞GUI?

[英]How to wait for threads to finish without blocking GUI?

我有2863個對象的數組。 我希望每1000個對象以兩次“運行”通過4個線程(正在運行PC#CPU)讀取數組數據。

目前,我的源代碼正在對數據進行分區以糾正線程數並運行:

單次運行大小(默認)= 1000個元素
運行次數= 2
額外的螺紋行程大小= 866個元素

開始跑步[1/2]
線程為readDCMTags(i = 0,firstIndex = 0,lastIndex = 249
線程為readDCMTags(i = 1,firstIndex = 250,lastIndex = 499
線程為readDCMTags(i = 2,firstIndex = 500,lastIndex = 749
線程為readDCMTags(i = 3,firstIndex = 750,lastIndex = 999

開始跑步[2/2]
線程為readDCMTags(i = 0,firstIndex = 1000,lastIndex = 1249
線程為readDCMTags(i = 1,firstIndex = 1250,lastIndex = 1499
線程為readDCMTags(i = 2,firstIndex = 1500,lastIndex = 1749
線程為readDCMTags(i = 3,firstIndex = 1750,lastIndex = 1999
額外的線程為readDCMTags(i = 1,firstIndex = 2000,lastIndex = 2865

但是,當前的源代碼會立即啟動所有線程,而不是在等待RUN TO END。 當我從當前運行中加入線程時,GUI正在掛出。 該如何解決呢?

源代碼是:

nrOfChunks = 2866 / 1000;
int leftOverChunk = 2866  % 1000;

for(int z = 0; z < nrOfChunks; z++)
{
    addToStatusPanel("\nStarting run [" + (z+1).ToString() + " / " + nrOfChunks.ToString() + "]");

    int indexesPerThread = 1000 / 5; #nrOfThreads
    int leftOverIndexes = 1000 % 5; #nrOfThreads

    threads = new Thread[nrOfThreads];
    threadProgress = new int[nrOfThreads];
    threadDCMRead = new int[nrOfThreads];

    for(int i = 0; i < nrOfThreads; i++)
    {
        int firstIndex = (i * indexesPerThread+z*Convert.ToInt32(chunkSizeTextBox.Text));
        int lastIndex = firstIndex + indexesPerThread - 1;

        if(i == (nrOfThreads- 1))
        {
            if(i == (nrOfThreads - 1))
            {
                lastIndex += leftOverIndexes;
            }
        }

        addToStatusPanel("readDCMTags(i=" + i.ToString() + ",firstIndex=" + firstIndex.ToString() + ", lastIndex=" + lastIndex.ToString());

        threads[i] = new Thread(() => readDCMTags(i.ToString(), firstIndex, lastIndex));
        threads[i].Name = i.ToString();

       threads[i].Start();
    }

    if(z == (nrOfChunks - 1))
    {
        int firstIndex = (nrOfChunks * Convert.ToInt32(chunkSizeTextBox.Text));
        int lastIndex = firstIndex + leftOverChunk - 1;

        addToStatusPanel("readDCMTags(i=" + z.ToString() + ",firstIndex=" + firstIndex.ToString() + ", lastIndex=" + lastIndex.ToString());
    }
}

for(int i = 0; i < nrOfThreads; i++)循環之后添加一個for(int i = 0; i < nrOfThreads; i++)線程數組的連接命令,然后再進行for(int z = 0; z < nrOfChunks; z++)下一個運行循環for(int z = 0; z < nrOfChunks; z++)將掛起GUI。

根據定義,如果您等待,則會阻塞(當前正在執行的線程會阻塞等待其他事件)。

相反,您想要的是在所有線程完成后發生某些事情。 那“所有線程都完成了”是一個事件。 因此,最好的選擇是在所有線程完成后在后台線程中等待並觸發事件。

如果GUI對此感興趣,則GUI線程將需要訂閱該特定事件。

編輯:偽代碼(未經測試,只是想法)。

waitBg = new Thread(() => 
  {
    foreach (thread in threads)
      thread.WaitFor();

     // All threads have finished
     if (allThreadFinishedEvent != null)
        allThreadFinishedEvent();
  }
);

然后,在allThreadFinishedEvent的處理程序上,您可以執行任何操作(如果要更改UI中的某些內容,請記住將其分派到主線程,因為它將在bg線程上下文中執行)。

如何將此線程邏輯放置在后台工作器中並將后台工作的結果發送回接口。 這樣,您的界面將不會在程序處理線程時被鎖定。

您可以在此處找到初始化和使用backgroundworker的msdn示例。

我認為這應該是正確的前進方向。

暫無
暫無

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

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