5

DispatcherTimerサーバーからシステムステータスを更新するために30秒ごとに起動するコードを実行しています。サーバーコードをデバッグしている場合でも、クライアントでタイマーが起動するため、5分間デバッグしていると、クライアントで12回のタイムアウトが発生する可能性があります。async最終的に私はこれを修正する必要があると判断したので、より/awaitフレンドリーなDispatcherTimerを作成しようとしています。

  • で実行されているコードDispatcherTimerは、再入可能であるかどうかに関係なく構成可能である必要があります(つまり、タスクがすでに実行されている場合は、再度実行しようとしないでください)。
  • タスクベースである必要があります(これで実際にタスクを公開する必要があるかどうかにかかわらず、ルートは灰色の領域です)
  • 非同期コードとawait実行するタスクを実行できる必要があります
  • DispatcherTimerをラップするか拡張するかはおそらく実際には問題ではありませんが、使用方法がわからない場合は、ラップすることで少しあいまいさが少なくなる可能性があります。
  • IsRunningUIのバインド可能なプロパティを公開する可能性があります
4

1 に答える 1

12

これが私が思いついたものです。

  • SmartDispatcherTimer拡張DispatcherTimer(これを起動して実行するための最も簡単な方法でした)
  • ロジックを処理するためのを提供するTickTaskプロパティがありますTask
  • プロパティがありIsReentrantます(もちろん、要点は、再入可能にしたくないので、通常、これは誤りです)
  • それはあなたが呼んでいるものが完全に待っていることを前提としています-さもないとあなたは再入可能性保護の利点を失うことになります

使用法:

        var timer = new SmartDispatcherTimer();
        timer.IsReentrant = false;
        timer.Interval = TimeSpan.FromSeconds(30);
        timer.TickTask = async () =>
        {
            StatusMessage = "Updating...";  // MVVM property
            await UpdateSystemStatus(false);
            StatusMessage = "Updated at " + DateTime.Now;
        };
        timer.Start();

これがコードです。それについての考えを聞きたいです

public class SmartDispatcherTimer : DispatcherTimer
{
    public SmartDispatcherTimer()
    {
        base.Tick += SmartDispatcherTimer_Tick;
    }

    async void SmartDispatcherTimer_Tick(object sender, EventArgs e)
    {
        if (TickTask == null)
        {
            Debug.WriteLine("No task set!");
            return;
        }

        if (IsRunning && !IsReentrant)
        {
            // previous task hasn't completed
            Debug.WriteLine("Task already running");
            return;
        }

        try
        {
            // we're running it now
            IsRunning = true;

            Debug.WriteLine("Running Task");
            await TickTask.Invoke();
            Debug.WriteLine("Task Completed");
        }
        catch (Exception)
        {
            Debug.WriteLine("Task Failed");
        }
        finally
        {
            // allow it to run again
            IsRunning = false;
        }
    }

    public bool IsReentrant { get; set; }
    public bool IsRunning { get; private set; }

    public Func<Task> TickTask { get; set; }
}
于 2012-09-15T21:28:07.870 に答える