5

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();
   }
}

どんな助けでも素晴らしいでしょう

4

2 に答える 2

7

ほとんどの場合、4 つのスレッドすべてが実行されます。

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

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

4 つのスレッドすべてが同じ値を使用する場合、コードが機能する可能性は低くなります。

于 2012-12-26T14:41:54.450 に答える
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();
于 2012-12-26T14:46:15.390 に答える