2012-12-26 8 views
5

スレッドが4つの別々のスレッドを作成し、終了するまで待っています。各スレッドはしばらくの間スリープし、共有されたmutex opbjectが別のスレッドで占有されていない場合に終了し、終了したイベントをトラブする(これはコードの単純化バージョンですが、同じ場所で失敗します)すべてのイベントが発生してもWaitOne()は永遠に待機します

何が起こるかは、メインスレッドが一見無作為にWaitOne()の1つで永遠に待機する時間の大部分です。

それがさらに予期しない動作につながったので、また、私は

(Ieは何とか各スレッドは、メインスレッドが句の背中にジャンプし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

[Tasks](http://msdn.microsoft.com/en-us/library/dd270695(v = vs.100).aspx)を使用してこのロジックをクリーンアップすることを検討してください。 – roken

+0

@roken:私はタスクが実行フローを混乱させないと思うが、これはそこにある、これはもっと多くのenatヘルパー/エクステンションとの非同期作業を行うための他の構造だ。 – sll

答えて

7

ほとんどの素晴らしいだろう、すべての4つのスレッドが実行されます:

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

これはclosuの使用に関係していますres。 4つのスレッドはすべて変数iにバインドされ、コードが実行された後の値はすべて使用されます(Threadオブジェクトが作成されたときの値ではありません)。

4つのスレッドがすべて同じ値を使用していると、コードは動作しない可能性があります。

+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(); 
関連する問題