c# - WaitOne() 永远等待,即使所有事件都已触发

标签 c# multithreading waitone

Threaded 应该创建 4 个独立的线程并等待它们中的每一个直到它们完成。每个线程休眠一段时间,只有当共享互斥对象没有被另一个线程占用时才终止,然后通过一个事件发出它完成的信号(这是我代码的简化版本,但在同一个地方失败)

但是大多数情况下,主线程似乎随机地永远等待 WaitOne() 之一。

我还不得不注释掉我的代码的某些部分,因为它导致了更多意想不到的行为(即在每个线程完成后主线程会以某种方式跳回 for 子句并导致 IndexOutOfBounds)

class Threading
{
    static Mutex CM;
    static List<Manga> SharedList;
    static ManualResetEvent CEvent = new ManualResetEvent(false);
    static ManualResetEvent Event1 = new ManualResetEvent(false);
    static ManualResetEvent Event2 = new ManualResetEvent(false);
    static ManualResetEvent Event3 = new ManualResetEvent(false);
    static ManualResetEvent Event4 = new ManualResetEvent(false);

   public List<Manga> ThreadedMangaIndexCrawl(int MaxThreads)
   {
       CM = new Mutex(false);
       SharedList = new List<Manga>();

       ManualResetEvent[] evs = new ManualResetEvent[4];
       evs[0] = Event1;    // Event for t1
       evs[1] = Event2;    // Event for t2
       evs[2] = Event3;    // Event for t3
       evs[3] = Event4;    // Event for t4

       /*for (int i = 0; i < MaxThreads + 1; i++)
       {
           if (i > MaxThreads)
           { break; }
           Thread t = new Thread(() => this.StartIndexCrawling(1,i,i+1,evs[i]));
           t.Start();
       }*/
       int i = 0;
       Thread t1 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i]));
       t1.Name = "Thread" + i;
       t1.Start();
       i++;
       Thread t2 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i]));
       t2.Name = "Thread" + i;
       t2.Start();
       i++;
       Thread t3 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i]));
       t3.Name = "Thread" + i;
       t3.Start();
       i++;
       Thread t4 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i]));
       t4.Name = "Thread" + i;
       t4.Start();


      /* foreach (var e in evs)
       { 
           e.WaitOne(); 

       }*/

       evs[0].WaitOne();
       evs[1].WaitOne();
       evs[2].WaitOne();
       evs[3].WaitOne(); 

       return SharedList;
   }

   void StartIndexCrawling(int Target, int Start, int End, ManualResetEvent E)
   {
       Thread.Sleep(1000);
       CM.WaitOne();
       CM.ReleaseMutex();
       E.Set();
   }
}

任何帮助都会很棒

最佳答案

最有可能的是,所有四个线程都将执行:

this.StartIndexCrawling(1, 3, 3 + 1, evs[4]);

这与您对闭包的使用有关。所有四个线程都将绑定(bind)到变量 i 并在执行代码后使用它具有的任何值(而不是创建 Thread 对象时的值)。

如果所有四个线程都使用相同的值,您的代码将不太可能正常工作。

关于c# - WaitOne() 永远等待,即使所有事件都已触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14041951/

相关文章:

c# - 如何取消阻塞已调用 AutoResetEvent 对象上的 WaitOne 方法的线程?

c# - 我如何知道我的项目的名称是什么?

c# - 流利的断言 : Assert one OR another value

c++ - 防止线程不必要的退出并使池保持事件状态

java - 黑莓 (Java) 中的线程间控制处理

c# - 对象锁不适用于线程安全

c# - DropDownList如何设置DataSource

multithreading - POSIX pthread 互斥锁和解锁中线程的等待队列在哪里?

c# - 如何等待一个BackgroundWorker完成来运行另一个BackgroundWorker(C#)?