0

このプログラミングゲームを参考に、現在制作中です。

Run次のようなもので構成されるメソッドを持つクラス ライブラリ (dll) があります。

public class MyRobot : Robot 
{
    public void Run(} 
    {
        while (true) 
        {
           Ahead(200); //moves the bot 200pixels
           TurnLeft(90); //turns the bot by 90deg 
        }
    }
}

これらのメソッド ( から継承Robot) では、システムは WPF を使用して (BeginAnimationまたは を使用してDispatcherTimer) ロボットをアニメートします。

さて、問題は、現在のメソッドを完了する前に戻る (つまり、次のメソッドに移動する) メソッドがないことです。これは、アニメーションが一緒に行われ、無限ループ (上の 1 つ)、それは特に良くありません。


私の質問は、アニメーションを完了する前にメソッドが戻らないようにする最善の方法は何ですか?

私は現在、アクションの実行が開始されたときにフラグが付けられるクラス ( ) を持っておりboolRobotその後isActionRunning、アニメーション コールバックで にtrue変更されます ( を使用する場合はイベントを使用します)。falseCompletedBeginAnimation

各メソッドの最後 (呼び出し後BeginAnimation) に、次のループを配置しました。

while (isActionRunning) 
{
    Thread.Sleep(200); //so that the thread sleeps for 200ms and then checks again if the animation is still running 
}

これは、アニメーションが終了する前にメソッドが戻らないようにするためです。

しかし、これはこれを行う正しい方法ではないと感じています。

これを達成するための最善の方法を教えてもらえますか?

4

3 に答える 3

5

ロックから信号装置を構築するのは狂気です。フレームワークに既に存在するシグナリング デバイスを使用するだけです。

http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx

つまり、スレッド 1 は、「ヘイ スレッド 2、このアニメーションを開始して、完了したらこの待機ハンドルで信号を送ってください」と言います。スレッド 1 は、waithandle で待機します。スレッド 2 はアニメーションを開始し、その完了イベントで待機ハンドルを通知します。スレッド 1 が再び起動し、「ヘイ スレッド 2、この別のアニメーションを開始してください...」と言います。

于 2010-04-01T14:48:52.093 に答える
3

ここに 1 つのオプションがあります。Robot.Run コードが、アニメーションを実行している UI スレッドとは異なるスレッドで実行されている場合にのみ機能します。

Robot.Ahead メソッド (たとえば) では、Dispatcher.Invoke (BeginInvoke ではない) を使用してアニメーションを開始するメソッドを呼び出し、空のブロック ( lock(this) { } ) でロボットにロックを追加します。

アニメーションを開始するメソッドで、アニメーションを開始する前に Monitor.Enter(robot) を呼び出します

アニメーション完了ハンドラで Monitor.Leave(robot) を呼び出します

結果は次のようになります。

time      robot thread          UI thread  
  |       ---------------       --------------  
  |       call Invoke    --->  
  |                             lock robot (Monitor.Enter)  
  |                             begin animation  
  |       Invoke returns <---   return  
  |       lock(this)            (animation running)  
  |       (wait for lock  
  |       to become available)  
  |  
  |                             Animation complete  
  |                             release lock (Monitor.Exit)  
  |       (lock available,  
  |       continue running)  
  |       Release lock (exit lock block)  
  |       Return and start next  
  |       movement  
  \/  
于 2009-03-11T09:18:17.340 に答える
0

私はあなたが説明したものと同様のことをします。私は最近、一連の非同期操作を呼び出す作業に取り組みましたが、別の操作を呼び出す前に、それらがすべて完了するのを待ちたいと思いました。現在実行中のすべての操作を表すコレクションを作成し、アイテムをコレクションに直接追加する代わりに、追加および削除するためのメソッドを作成しました。remove メソッドには、「コレクションをロックし、提供されたキーを削除し、空の場合は次の操作を呼び出す」というロジックがありました。アプリケーションまたはウィンドウをスコープとするコレクションが実行中の操作を追跡する、このような同様のメカニズムを作成できます。コレクションにキーを追加し、このキーを非同期操作に渡します。非同期操作が完了したら、コレクションをロックしてキーを削除します。

これはやり過ぎかもしれませんが、私はこの問題に関する経験が限られています。私が知っている限りでは、.Net には、1 行または 2 行のコードで機能する、この問題に対する既定の解決策さえあるかもしれません。

于 2009-03-10T23:01:26.590 に答える