我有2863个对象的数组。我想在每1000个对象的两个“运行”中通过4个线程读取数组数据(运行PC#的CPU)。
Currenly我的源代码是将数据分区为正确的线程数并运行:
单次运行大小(默认)= 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。
答案 0 :(得分:3)
根据定义,如果你等待,你阻塞(当前正在执行的线程阻塞等待其他东西)。
相反,你想要的是在所有线程完成后发生的事情。那个“所有线程已经完成”是一个事件。因此,最好的选择是在后台线程中等待,并在所有线程完成时触发事件。
如果GUI对此感兴趣,那么GUI线程将需要订阅该特定事件。
编辑:伪代码(未经测试,只是想法)。
waitBg = new Thread(() =>
{
foreach (thread in threads)
thread.WaitFor();
// All threads have finished
if (allThreadFinishedEvent != null)
allThreadFinishedEvent();
}
);
然后,在allThreadFinishedEvent的处理程序上,您可以执行任何操作(如果要在UI中更改某些内容,请记住将其分派给主线程,因为这将在bg线程上下文中执行)。
答案 1 :(得分:0)
如何将此线程逻辑放在后台工作程序中,并将后台工作程序的结果发送回您的界面。这样,在程序处理线程时,您的界面不会被锁定。
你可以找到初始化和使用backgroundworker here的msdn示例。
我认为这应该是正确的前进方式。