4

これは少し奇妙な設定で、やり直すつもりですが、少なくとも、この結果としてスレッドについてもっと多くを学べることを願っています.

現在、TabControl Windows フォームを設計の基礎として使用するアプリケーションを作成しています。やらなければならないことがたくさんあるので、これが最善の方法かもしれないと考えました。

現在、ユーザーがマウスとキーボードの操作を記録および再生できるように、マクロ関数をプログラムにコーディングしています。それはまったく問題なく、System.Timers.Timer との混合も問題ありませんでした。ただし、私が使用している DLL は、Thread.Sleep(x) を使用して、キーストロークとマウスの実行の間にスレッドを一時停止します。

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

もう少し詳しく説明するには:

  • ユーザーがメイン タブ コントロールのボタンをクリックします。
  • 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 ページであり、マクロは Web ページのフォームで実行されます。

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

また、「Thread.CurrentThread.Abort」はスレッドセーフであるため、スレッドを完全に終了したい場合にスレッドを終了するための優れた方法であると通知されましたが、スレッドを強制終了するのではなく、スレッドにその機能を繰り返させることができれば、それは素晴らしい...

4

1 に答える 1

1

再生スレッドを再利用するには、メイン スレッドから取得したAutoResetEventを使用できます。Set()スレッドがアイドル状態の場合も同様です。メイン スレッドは再生に必要なデータを準備し、次にSet()別のデータを準備しAutoResetEventて、再生スレッドを開始します。

したがって、startPlayingAutoResetEvent以下の例では、メイン スレッドが「実行」するように指示するまでスレッドを待機させますがstopPlayingAutoResetEvent、ステップを実行していないときは常にメイン スレッドに「停止」するように指示するメイン スレッドに再生スレッドが応答するようにします。

メインスレッド:

// 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
        }
    }
}
于 2012-05-09T09:50:53.047 に答える