2012-05-09 31 views
4

これはちょっと変わった設定ですが、やり直しを計画していますが、もし何もなければ、この結果としてスレッディングについて多くのことを学ぶことができると期待しています。Cでのスレッディング+ TabControl

現時点では、TabControl Windowsフォームをデザインの基礎として使用しているアプリケーションを作成しています。私は、私がする必要があるさまざまなことがたくさんあるので、これはそれを行うための最良の方法かもしれないと思った。

ここでは、マクロ機能をプログラムにコーディングしています。これにより、ユーザーはマウスとキーボードの動作を録音して再生できます。それはまったく問題なく、System.Timers.Timerと混合することもOKです。しかし、私が使用しているDLLは、Thread.Sleep(x)を使用して、キーストロークとマウスの実行の間にスレッドを一時停止します。

この時点で、ボタンは別のタブページにあり、別のページに切り替わります。ただし、マクロの実行が完了するのを待っている間に、ポイントブランク設定でプログラムがハングしました。

少し良く説明すること:

  • ユーザーは、メインのTabControlのボタンをクリックします。
  • Tabcontrol.SelectedIndexが適切なページに切り替えられますが、ページを更新していません(私はthis.Refresh()を呼び出してみました、それは動作しませんでした)
  • マクロを実行
  • TabControlのは、ページのロードが終了、しかしによってこの時点で、必要なマクロは既に実行されており、ロードされたページは余計です。

これを回避するために、私はスレッディングを調査し、どのように使用できるかを見始めました。私は、クラス内の次のコードを思い付いた:

Class X{ 
    Thread othread; 
    ...   
    public void Play() 
    { 
    if ((othread != null) && !(othread.IsAlive)) 
    { 
     othread = new Thread(playValues); 
     GC.Collect(); 
    } 
    else if (othread == null) othread = new Thread(playValues); 
    else return; 
    othread.Start(); 
    } 

    public void PlayValues(){ 
    ... 
    Thread.CurrentThread.Abort(); 
    } 

} 

ユーザーがメインフォームで「再生」をクリックするたびに、X.Play()が呼び出され、ため、スレッドが破棄される理由があるので、私はどちらかのスレッドを再利用する必要があります(私はMonitor.Pulse()を調べましたが、私に非同期呼び出しエラーを与えました)、または完了するたびに永久に破棄してください。

現在のところ、コードは正常に動作します。しかし、私がマクロを実行しなければならないたびにスレッドを一貫して作成して破壊しているという事実は、ちょっと気になりますが、ばかげたGC呼び出しも心配です。

この設定を行わなくても、スレッド化に関するいくつかの指針を得ることができますか?実際、セカンダリタブはウェブページであり、マクロはウェブページのフォーム上で実行されます。

  • 編集:これを明確にしていないかどうかはわかりませんが、マクロはマウスとキーボードのシミュレータを使用しています。もう一方のタブはWebブラウザの設定で、内部にアプレットをネストするので、自動設定を実行するためにハードウェア機能をエミュレートしています。これは私が何もロックする必要はないので(マウスとキーボードの呼び出しはすべてシミュレータによって操作され、3次タブで制御される値には関係しません)、私はスレッドにユーザがボタンを押すたびに同じ機能を実行し、b)余分な材料の一部を取り除く。

私はまた、あなたは永遠にそれを終了したい場合は、「Thread.CurrentThread.Abort」はスレッドセーフので、スレッドを終了する細かい方法であることを知らされたが、私はスレッドがその機能を繰り返す代わりに殺すことができた場合それはすばらしいでしょう...

+1

問題1:しないでください(これまでは) 'GC.Collect()'を呼び出します。 –

+0

@HenkHoltermanはナンセンスです。 GC.Collect()を呼び出すためのいくつかの有効なシナリオがあります。 huseビットマップアイテムをロードした後 – CodingBarfield

+0

@CodingBarfield:実際にはいくつかの例外がありますが、これは1のようには見えません。 –

答えて

1

再生スレッドを再利用するには、メインスレッドのSet()であるAutoResetEventを使用します。スレッドがアイドル状態の場合も同様です。メインスレッドは再生に必要なデータを準備し、次にSet()は別のAutoResetEventです。これにより、再生スレッドが開始されます。

したがって、stopPlayingAutoResetEventは、実行スレッドが実行中でないときはいつでも、メインスレッドに応答してメインスレッドに応答するようになるまで、スレッドはメインスレッドが "go"になるまで待機します。一歩。

メインスレッド:

// prepare data to play 
startPlayingAutoResetEvent.Set(); 
// ... 
stopPlayingAutoResetEvent.Set(); 

プレイスレッド:

while (true) 
{ 
    // wait for the main thread to signal "start" 
    startPlayingAutoResetEvent.WaitOne(); 
    // ensure the stopPlaying is in an unsignalled state 
    stopPlayingAutoResetEvent.Reset(); 

    // gather the data the main thread has prepared 

    while (stepsToPlay) 
    { 
     // wait until main thread signals to stop OR timeout has elapsed 
     if (stopPlayingAutoResetEvent.WaitOne(timeout)) 
     { 
      // abort current run and put thread in idle mode, waiting for new commands 
      break; 
     } 
     else 
     { 
      // play next step 
     } 
    } 
} 
+0

クール! AutoResetEventについて知りませんでした。しかし、私はそれをもっと見てきましたが、スレッドの関数を繰り返し呼び出す必要があるということは必ずしも十分ではありません。あなたのプロセスをもう少し説明できますか? しかし、私は間違いなく実装のためのThread.Sleepの代わりにそれを使用しています。 :Dありがとう! –

+0

私は少し私の答えを更新しました。おそらく、両方のスレッドがマルコのデータにアクセスするコード内の部分を「ロック」し、そのスレッドのローカルコピーで再生スレッドを動作させたいと思うかもしれません。 –

+0

秒待ってください。スレッドを実行させてもスレッドは自動ループしますか? 編集:決して気にしない、あなたがしたことを見ている。クール! :Dありがとう、それは大きな助けです。 –