2016-03-30 24 views
4

私はC#でマルチスレッドプログラミングに触れていません。私の問題は、次の行に進む前に別のスレッドで実行されているメソッドが完了するのを待つ方法がわからないことです。たとえば、このメソッドが別のスレッドで終了するのを待つ方法は?

public class A 
{  
    int i; 

    public A() 
    { 
     i = 0; 
    } 

    protected void RunLoop() 
    { 
     while(i < 100) 
     { 
      i++; 
     } 
    } 

    public void Start() 
    { 
     TimerResolution.TimeBeginPeriod(1); 
     runThread = new Thread(new ThreadStart(RunLoop)); 
     running = true; 
     runThread.Start(); 
    } 
} 

public class B 
{ 
    A classAInstance = new A(); 
    A.Start(); 
    Console.Writeline(i); 
} 

のようなものは今のところ、それは(すなわち、I = 100)私が欲しいものではありませんこれは、コンソール上で0を出力します。 これを行う最善の方法は何ですか?ところで、私はclass A

おかげで作成されrunThreadにアクセスすることはできません。

EDIT:

それはたくさんのコードを変更せずに、この問題を解決するために少し難しかったです。したがって、我々は別のスレッドでRunLoopを実行するかどうかを決定できる条件を、public void Start()に追加することになりました。条件はEnumフィールドを使用して定義されました。

public void Start() 
{ 
    TimerResolution.TimeBeginPeriod(1); 
    running = true; 
    if (runningMode == RunningMode.Asynchronous) 
    { 
     runThread = new Thread(new ThreadStart(RunLoop)); 
     runThread.Start(); 
    } 
    else 
    { 
     RunLoop(); 
    } 
} 

そして

public enum RunningMode { Asynchronous, Synchronous }; 

助けてくれてありがとうみんなを。

+3

あなたが他のコードにアクセス全くない場合、あなたはおそらく他のスレッドで何が起こっているかを検出することはできません。スレッドインスタンスへのアクセス権があれば、 'Thread.Join'を使って終了するのを待つことができますが、もしそれがなくても問題は解決できません。同期には協力が必要です。 –

+0

ちなみに、私たちは 'A.i'へのアクセス権がないので、あなたのコードをコンパイルすることはできません(もしそうであれば、スレッドセーフではありません)。だから、あなたのスレッドは状態を共有しているのですか、そうではありませんか?あなたの*実際の問題は何ですか?なぜ、明示的なスレッディングが必要だと思いますか? –

+0

*スレッドを使用する代わりに、タスクが終了したら何らかのアクションをとるためにTasksと 'await'、' ContinueWith'、 'Wait()'などを使います。あなたが記述したシナリオを簡素化するために作成されたものです(最低でも) –

答えて

0

私はMonitor.Wait()とMonitor.Pulse()を "lock"演算子と併用するのが好きです。それは動作しますが、このテクニックを使用するときは注意が必要です。 コードを変更するためにいくつかの変更が加えられました。以下のコードは、i == 100のプリントです。

public class A 
{ 
    int i; 

    public object SyncObject 
    { get; private set; } 

    public A() 
    { 
     SyncObject = new object(); 
     i = 0; 
    } 

    protected void RunLoop() 
    { 
     while (i < 100) 
     { 
      i++; 
     } 

     lock (SyncObject) 
     { 
      Monitor.Pulse(SyncObject); 
     } 
    } 

    public void Start() 
    { 
     var runThread = new Thread(new ThreadStart(RunLoop)); 
     runThread.Start(); 
    } 

    public void PrintI() 
    { 
     Console.WriteLine("I == " + i); 
    } 
} 

public class B 
{ 
    public static void Run() 
    { 
     A classAInstance = new A(); 
     lock (classAInstance.SyncObject) 
     { 
      classAInstance.Start(); 
      Monitor.Wait(classAInstance.SyncObject); 
     } 
     classAInstance.PrintI(); 
    } 
} 
2

好ましい方法は、Task Parallel Library(TPL)を使用し、awaitTaskを使用することです。

スレッドを使用する必要がある場合は、ManualResetEventまたはManualResetEventSlimを使用してメソッドの終了を知らせます。

void Main() 
{ 
    var a = new A(); 
    a.Start(); 
    a.FinishedEvent.WaitOne(); 
    Console.WriteLine(a.Index); 
} 

// Define other methods and classes here 
public class A 
{ 
    ManualResetEvent mre = new ManualResetEvent(false); 
    int i; 

    public EventWaitHandle FinishedEvent 
    { 
     get { return mre; } 
    } 

    public int Index 
    { 
     get { return i; } 
    } 

    public A() 
    { 
     i = 0; 
    } 

    protected void RunLoop() 
    { 
     while (i < 1000) 
     { 
      i++; 
     } 
     mre.Set(); 
    } 

    public void Start() 
    { 
     var runThread = new Thread(new ThreadStart(RunLoop)); 
     runThread.Start(); 
    } 
} 
2

あなたの人生は仕事によってずっと良いでしょう。

あなたのコードは、この単純なことができます

var task = Task.Factory.StartNew(() => 
{ 
    var i = 0; 
    while (i < 100) 
    { 
     i++; 
    } 
    return i; 
}); 

Console.WriteLine(task.Result); 
+0

そこには 'task.Wait()'が必要です.OPはプロセスの終了を待つ方法を尋ねています – Jcl

+4

@Jcl、 'task.Result'は' task.Wait() 'と同じブロッキング呼び出しです。 –

+0

@KirillShlenskiyオハイオ州、それはまったく正しい、私の悪い! – Jcl

関連する問題