2009-07-31 4 views
5

私は通常5つのスレッドを開始するプログラムを作成しています。スレッドは、非確定的な順序で戻ります。各スレッドはListを返すメソッドを呼び出しています。.NETでデータを返すスレッド

私はこれやってる:だからここ

var masterList = List<string>();  
foreach (var threadParam in threadParams) 
{ 
    var expression = threadParam ; 
    ThreadStart sub =() => MyMethod(expressions); 
    var thread = new Thread(sub) 
    { 
     Name = expression 
    }; 

    listThreads.Add(thread); 
    thread.Start(); 
} 

var abort = true; 
while (abort) //Wait until all threads finish 
{ 
    var count = 0; 
    foreach (var list in listThreads) 
    { 
     if (!list.IsAlive) 
     { 
      count++; 
     } 
    } 

    if (count == listThreads.Count) 
    { 
     abort = false; 
    } 
} 

は問題です:

各スレッドには、それは私がmasterListを追加したいリストを前に宣言リターンを終了したとき。

これについてはどうすればよいですか?

また、私は(私はいくつかの中でManualResetEventクラスを使用しましたWaitHandleクラスとWaitHandle.WaitAllをチェック

var abort = true; 
while (abort) //Wait until all threads finish 
{ 
    var count = 0; 
    foreach (var list in listThreads) 
    { 
     if (!list.IsAlive) 
     { 
      count++; 
     } 
    } 

    if (count == listThreads.Count) 
    { 
     abort = false; 
    } 
} 

答えて

14

WaitHandle


を使用します。ここです例:

using System; 
using System.Threading; 

class ThreadSleeper 
{ 
    int seconds; 
    AutoResetEvent napDone = new AutoResetEvent(false); 

    private ThreadSleeper(int seconds) 
    { 
     this.seconds = seconds; 
    } 

    public void Nap() 
    { 
     Console.WriteLine("Napping {0} seconds", seconds); 
     Thread.Sleep(seconds * 1000); 
     Console.WriteLine("{0} second nap finished", seconds); 
     napDone.Set(); 
    } 

    public static WaitHandle DoSleep(int seconds) 
    { 
     ThreadSleeper ts = new ThreadSleeper(seconds); 
     Thread thread = new Thread(new ThreadStart(ts.Nap)); 
     thread.Start(); 
     return(ts.napDone); 
    } 
} 

public class OperationsThreadsWaitingwithWaitHandle 
{ 
    public static void Main() 
    { 
     WaitHandle[] waits = new WaitHandle[2]; 
     waits[0] = ThreadSleeper.DoSleep(8); 
     waits[1] = ThreadSleeper.DoSleep(4); 

     Console.WriteLine("Waiting for threads to finish"); 
     WaitHandle.WaitAll(waits); 
     Console.WriteLine("Threads finished"); 
    } 
} 

のリンクをチェックアウトする:

+1

私と同じアイデア...しかし、より良い答え:( –

0

を完了するためにすべてのスレッドを待つために、以下のより良い方法があるに違いありません知っています私のWaitHandleのコードですが、それは単なる例です。状況に適したものがあるかどうかは分かりません)。 5つのスレッドをすべて消し、マスターリストへの参照を与え、追加するときにこのリストをロックしてから完了を通知します。 WaitHandle.WaitAllを使用して、5つすべてが完了したことを通知するまでブロックします。

2

各スレッドを独自のオブジェクトにするのが最善の方法です。他のオブジェクトと混ざり合ってはいけません。あなたが行うのは(変数を渡して)自分自身をリスナーとして追加して起動することだけです。

これが完了すると、メンバー変数に値が格納され、リスナーに通知されます。

リスナーは、余暇に値を取得できます。リスナーに直接値を返す

明白なショートカット、動作しますが、あなたは、このバージョンより柔軟後に(そして実際にはあまり多くのコード)を見つけることが

1

もちろん、正規の代理人とAPMを使用することもできます。

説明するパターンは通常、後で何かを返すことを約束するバックグラウンドジョブであるFutureと記述されています(可能な場合は投資収益率)。

ここでは、コンソールプログラムの形式の簡単な例を示します。

出力:私は明示的にスレッドを作成いないよので、もちろん

sequential: 3224 ms 
parallel: 2074 ms 

は、私が並行して実行するためにどのように多くのスレッドを把握するスレッドプールシステムに任せます。

など、バックグラウンドスレッドが完了したときの通知をする条項、コールバックメソッドを介して、同様にWaitHandleのサポートを明示的にチェックし、タイムアウトを待っているために、

そしてソースもあります:

using System; 
using System.Collections.Generic; 
using System.Threading; 
using System.Diagnostics; 

namespace SO1215227 
{ 
    public class Program 
    { 
     public static void Main() 
     { 
      Stopwatch sw = new Stopwatch(); 
      sw.Start(); 
      var list1 = Sequence(1, 100); 
      var list2 = Sequence(101, 200); 
      var list3 = Sequence(201, 300); 
      sw.Stop(); 
      Console.Out.WriteLine("sequential: " + sw.ElapsedMilliseconds + " ms"); 
      sw.Reset(); 

      Func<Int32, Int32, List<Int32>> listProducer = Sequence; 
      sw.Start(); 
      var list1Background = listProducer.BeginInvoke(1, 100, null, null); 
      var list2Background = listProducer.BeginInvoke(101, 200, null, null); 
      var list3Background = listProducer.BeginInvoke(201, 300, null, null); 

      list1 = listProducer.EndInvoke(list1Background); 
      list2 = listProducer.EndInvoke(list2Background); 
      list3 = listProducer.EndInvoke(list3Background); 
      sw.Stop(); 
      Console.Out.WriteLine("parallel: " + sw.ElapsedMilliseconds + " ms"); 

      Console.Out.Write("Press enter to exit..."); 
      Console.In.ReadLine(); 
     } 

     private static List<Int32> Sequence(Int32 from, Int32 to) 
     { 
      List<Int32> result = new List<Int32>(); 
      for (Int32 index = from; index <= to; index++) 
      { 
       result.Add(index); 
       Thread.Sleep(10); // simulate I/O wait 
      } 
      return result; 
     } 
    } 
} 
は、