2012-12-26 19 views
5

螺纹被阻止以创建4个独立的线程并等待每个线程完成。每个线程休眠一段时间,只有当共享Mutex opbject没有被另一个线程占用,然后通过它完成的事件发出信号时才终止(这是我的代码的简化版本,但在同一个点失败)即使所有事件都被触发,WaitOne()仍然会一直等待

但是会发生什么情况是大多数时候主线程会在WaitOne()的一个表面上随机等待。

此外,我不得不注释掉我的代码的一些部分,因为它导致了更意外的行为(即在某种程度上每个线程完成主线程会跳回的条款,并导致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(); 
    } 
} 

任何帮助将是巨大的

+0

你创建这些对象不止一个?静态成员对于非单例对象看起来相当危险。 –

+0

考虑使用[任务](http://msdn.microsoft.com/zh-cn/library/dd270695(v = vs.100).aspx)清理此逻辑。 – roken

+0

@roken:我认为任务不会清理执行流混乱,这只是一个其他构造,可以与更多的帮助器/扩展进行异步工作。 – sll

回答

7

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

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

这与您使用的瓶盖做水库。所有四个线程都将绑定到变量i,并使用代码执行后的任何值(而不是创建Thread对象时的值)。

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

+0

也检查出这个帖子http://stackoverflow.com/questions/271440/c-sharp-captured-variable-in-loop – sll

+0

我会被诅咒。这是我认为的最后一件事。但为什么线程用当前的i执行自己,而不是通过参数来执行它们? //编辑刚刚在发布后看到链接 – user1927074

+0

在'StartIndexCrawling'内有一个值的本地副本。但是线程的最顶层代码是由闭包'()=> this.StartIndexCrawling(1,i,i + 1,evs [i])''定义的匿名函数。而这段代码引用了共享变量'i'。这就是关闭如何工作。 – Codo

0

查看Codo的回答。
这里是你应该做的事情来解决这个问题:

int i = 0; 
    Thread t1 = new Thread(() => this.StartIndexCrawling(1, 0, 1, Event1)); 
    t1.Name = "Thread" + i; 
    t1.Start(); 
    i++; 
    Thread t2 = new Thread(() => this.StartIndexCrawling(1, 1, 2, Event2)); 
    t2.Name = "Thread" + i; 
    t2.Start(); 
    i++; 
    Thread t3 = new Thread(() => this.StartIndexCrawling(1, 2, 3, Event3)); 
    t3.Name = "Thread" + i; 
    t3.Start(); 
    i++; 
    Thread t4 = new Thread(() => this.StartIndexCrawling(1, 3, 4, Event4)); 
    t4.Name = "Thread" + i; 
    t4.Start(); 
相关问题