在Set()完成一次后,ManualResetEventSlim Wait()不起作用

时间:2013-12-09 06:24:45

标签: c# multithreading

我想做什么

我有一些线程(例如,线程1,线程2,线程3)和整数队列(例如1,2,3)。 每一秒,我想暂停当前正在运行的线程,并从队列中弹出,并运行具有相同ID的线程。

例如:

假设我有一个线程数组,以及一个保存当前正在执行的线程的整数。

int[] myThread; //1, 2, 3
ManualResetEventSlim[] mre;  
executing = 1;
Queue myQueue; //2, 3

Time 0:01    //Thread 1 is running
Time 0:02    mre[executing].Wait();
             myQueue.Enqueue(executing);
             int nextThread = myQueue.Dequeue(); //say 2
             mre[nextThread].Set();
             executing = nextThread;
Time 0:03    //Same thing as at 0:02... 
Time 0:04    //Same above
Time 0:05    //Same above   

并希望输出看起来像这样:

Time 0:01    I'm 1
             I'm 1
             I'm 1
Time 0:02    I'm 2 // thread 2 was selected
             I'm 2
             I'm 2
Time 0:03    I'm 3 // thread 3 was selected
             I'm 3
             I'm 3
Time 0:04    I'm 2 // thread 2 was selected
             I'm 2
             I'm 2

我正在做什么

我有一个定义操作的主文件:

static void Main()
{
    CreateThread(Action, n);
}

public static void Action(int pid)
{
    for(int i=0; i<100000; i++)
    {
        Trace.WriteLine("I'm "+ pid);
    }
}

问题

问题是一旦使用Set()设置了一个线程,就不能再使用Wait()来阻止它。因此,每个线程都会一直执行整个Action方法,直到完成为止。

和输出看起来像这样:

Time 0:01    I'm 1    //Only Thread 1 is unblocked
             I'm 1
             I'm 1    
Time 0:02    I'm 2    //Thread 2 was unblocked. 
             I'm 1    //Thread 1 is not blocked, so it keeps printing
             I'm 2
Time 0:03    I'm 3    //Thread 3 was unblocked.   
             I'm 1    //Thread 1 is not blocked
             I'm 2    //Thread 2 is not blocked either

我一直在研究这个问题并且卡住了。我真的很感激任何帮助。

1 个答案:

答案 0 :(得分:0)

我不确定我是否理解这个问题,但我会更改Action(),以便它需要ThreadData的实例。你需要它来检查是否设置了MRE。如果是这样,请跳出迭代,让框架在线程之后进行清理。

public static void Action(ThreadData threadData)
{
    for (int i = 0; i < 100000; i++)
    {
        if (threadData.Mre.IsSet)
        {
            break;
        }
        Trace.WriteLine("I'm " + threadData.Pid);
    }
}

修改

您可能没有意识到,但您可能正在为每个线程使用相同的MRE实例。每个线程都引用mre变量。在将mre设置为新实例之前,谁会说该线程已启动?剧透:它没有。