2012-12-26 53 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(); 
相關問題