0

我有 2863 个对象的数组。我希望每 1000 个对象有两次“运行”,通过 4 个线程(运行 PC # of 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 z = 0; z < nrOfChunks; z++)挂起 GUI。

4

2 回答 2

3

根据定义,如果你等待,你就会阻塞(当前正在执行的线程阻塞等待其他东西)。

相反,您想要的是在所有线程完成时发生一些事情。也就是说,“所有线程都已完成”是一个事件。因此,您最好的选择是在后台线程中等待并在所有线程完成时触发事件。

如果 GUI 对此感兴趣,那么 GUI 线程将需要订阅该特定事件。

编辑:伪代码(未经测试,只是想法)。

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

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

然后,在 allThreadFinishedEvent 的处理程序上,您可以做任何您想做的事情(如果您想更改 UI 中的某些内容,请记住将其分派到主线程,因为这将在 bg 线程上下文中执行)。

于 2013-10-17T11:02:53.017 回答
0

将这个线程逻辑放在后台工作程序中并将你的后台工作程序的结果发送回你的界面怎么样。这样,当程序处理线程时,您的界面将不会被锁定。

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

我认为这应该是正确的前进方向。

于 2013-10-17T10:53:22.760 回答