9

絵コンテを使って写真をアニメーション化しています。アニメーションごとに計算を含む操作を実行してから、別のアニメーションを実行したいので、StoryBoardの完成したイベントを使用する必要があると思います。MyStoryboard.Completed += storyboard_Com​pleted;

私が興味を持っているのは、現在のストーリーボードで次のアニメーションを開始する必要があるStoryboard_Completed Eventかどうかです。また、Application.Current.Dispatcherオブジェクトを使用して別のスレッドで最初のアニメーションを開始した場合、何か影響はありますか?

Application.Current.Dispatcherを使用して別のスレッドでStoryBoard.Begin()を呼び出した場合、Storyboard_CompletedイベントもUIスレッドで呼び出されますか?この場合でも、次のアニメーションを別のディスパッチャー呼び出し内にラップする必要がありますか?

private void Story_Completed(object sender, EventArgs e)
{
    Application.Current.Dispatcher.Invoke((Action)delegate()
    {
       SomeNewStoryBoardAnimation.Begin();
    }
}

これは正しいです?または、ストーリーボードが終了したかどうかを確認し、その直後に次の一連の計算とストーリーボードアニメーションを開始するためのより良い方法はありますか?

単一のバックグラウンドワーカーを使用してすべてのアニメーションと計算を順番に処理することを考えましたが、次の計算とアニメーションのセットを開始する前に、アニメーションが完了するのを「待つ」方法も考えています。Thread.sleepアニメーションが完了するのを待っている間にBackGroundWorkerがいるのは正常ですか?

4

2 に答える 2

9

ストーリーボードをタスクオブジェクトでラップして、その完了を待つことができます。

これは、 Morten Nielsenによるブログ投稿から抜粋した、まさにそれを行う方法を示す優れたサンプルコードです。

public static class StoryboardExtensions
{
    public static Task BeginAsync(this Storyboard storyboard)
    {
        System.Threading.Tasks.TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
        if (storyboard == null)
            tcs.SetException(new ArgumentNullException());
        else
        {
            EventHandler<object> onComplete = null;
            onComplete = (s, e) => {
                storyboard.Completed -= onComplete; 
                tcs.SetResult(true); 
            };
            storyboard.Completed += onComplete;
            storyboard.Begin();
        }
        return tcs.Task;
    }
}

基本的に、ストーリーボードの完了を通知するTaskオブジェクトを返す拡張メソッドを作成しています。このようにして、次のような優れた流動的な構文が得られます。

//Start the storyboard and asynchronously await completion...
await myStoryboard.BeginAsync();

//Do my other stuff here, after the storyboard completes...
于 2013-02-04T20:55:29.960 に答える
1

Storyboard.Completedイベントを使用すると、目的に応じて機能するはずです。Storyboard.CompletedイベントハンドラーはUIスレッドで起動する必要があるため、Application.Current.Dispatcher.Invokeを呼び出して2番目のストーリーボードを起動する必要はありません。

元のストーリーボードを呼び出す場合、影響はありません。Application.Current.Dispatcher.Invokeの使用を開始します。これは、新しいスレッドでストーリーボードアニメーションを起動しません。メインUIスレッドでアニメーションを非同期的に呼び出します。UIスレッドでBeginを自分で呼び出す場合でも、Application.Current.Dispatcher.Invokeを使用して呼び出す場合でも、最終的な結果は同じになります。完了したイベントハンドラーはストーリーボードが終了すると起動し、計算を実行して次のストーリーボードを起動できます。

UIスレッドで実行されるため、過去にタイマーとして使用されていたストーリーボードの説明については、次の質問を参照してください。

ストーリーボードをタイマーとして使用する意味は何ですか?

また、これは、説明している特定のケースではおそらくやり過ぎですが、一連の順次非同期操作を調整する必要がある場合は、ReactiveExtensionsを使用できます。

http://msdn.microsoft.com/en-us/data/gg577609.aspx

次の記事には、連続したストーリーボードの例が含まれています(ただし、記事は十分に古いため、構文が変更されている可能性があります)。

http://www.wintellect.com/cs/blogs/jlikness/archive/2010/08/22/coroutines-for-asynchronous-sequential-workflows-using-reactive-extensions-rx.aspx

于 2013-02-05T06:23:11.983 に答える