2017-09-16 6 views
0

ユーザのアクティブ/非アクティブステータスを検出するプレゼンスモニタクラスがあります。 「確認」の方法は、すべての1分後に解雇されasyncはタイマーでは動作しません。

public class PresenceMonitor 
{ 
    private volatile bool _running; 
    private Timer _timer; 
    private readonly TimeSpan _presenceCheckInterval = TimeSpan.FromMinutes(1); 


    public PresenceMonitor() 
    { 
    } 

    public void Start() 
    { 
     // Start the timer 
     _timer = new Timer(_ => 
     { 
      Check(); 
     }, null, TimeSpan.Zero, _presenceCheckInterval); 
    } 

    private void Check() 
    { 
     if (_running) 
     { 
      return; 
     } 

     _running = true; 

     // Dowork 
    } 
} 

:そのクラスは、アプリケーションの起動時に呼び出され、そのStartメソッドでタイマーを持っています。コードのその部分は正常に動作しているが、今の私の「仕事をする」方法が非同期になってきたので、私はこのような何かにこのプレゼンスモニターのクラスを変更しなければならなかった待つ:

public class PresenceMonitor 
{ 
    private volatile bool _running; 
    private Timer _timer; 
    private readonly TimeSpan _presenceCheckInterval = TimeSpan.FromMinutes(1); 


    public PresenceMonitor() 
    { 
    } 

    public void Start() 
    { 
     // Start the timer 
     var timer = new System.Threading.Timer(async (e) => 
     { 
      await CheckAsync(); 
     }, null, TimeSpan.Zero, _presenceCheckInterval); 
    } 

    private async Task CheckAsync() 
    { 
     if (_running) 
     { 
      return; 
     } 

     _running = true; 

     // await DoworkAsync 
    } 
} 

今一度解雇され残念ながら「CheckAsync」方法毎分の代わりにのみです。あなたは私が非同期と呼ぶためにここで間違っていることを定期的な間隔の後で待っていますか?

同じことを行う正しい方法はありますか?

+0

これが解決しましたか? – Nkosi

答えて

3

タイマーの目盛りを処理してチェックを呼び出すイベントとハンドラーを作成することを検討できます。

public class PresenceMonitor { 
    private volatile bool _running; 
    private Timer timer; 
    private readonly TimeSpan _presenceCheckInterval = TimeSpan.FromMinutes(1); 

    public PresenceMonitor() { 
     Tick += OnTick; 
    } 

    public void Start() { 
     if (_running) { 
      return; //already running 
     } 
     // Start the timer 
     timer = new System.Threading.Timer(_ => { 
      Tick(this, EventArgs.Empty);//rasie event 
     }, null, TimeSpan.Zero, _presenceCheckInterval); 
    } 

    private event EventHandler Tick = delegate { }; 
    private async void OnTick(object sender, EventArgs args) { 
     if (_running) { 
      return; 
     } 
     _running = true; 
     await DoworkAsync(); 
    } 

    private Task DoworkAsync() { 
     //... 
    } 
} 
+0

この返信を見るためにガチョウ斑を持っています。これにあなたの努力をいただきありがとうございます。 – Raghav

+0

それは "private非同期タスクDoworkAsync()"であるべきですか? – Raghav

+0

@Raghav、そのメソッド内で 'await'を使用している場合のみです。どのようにメソッドがどのように見えるのか分かりません。 – Nkosi

0

要件を正しく理解していれば、タイマーを取り除いて非同期ループを使用できます。
しかし、あなたはあまりにも

public class PresenceMonitor 
{ 
    private volatile bool _running; // possible not needed "volatile" anymore 
    private readonly int _presenceCheckInterval = 60000; // Milliseconds 

    public PresenceMonitor() 
    { 
    } 

    public async Task Start() 
    { 
     while (true) // may be use some "exit" logic 
     { 
      await CheckAsync(); 
      await Task.Delay(_presenceCheckInterval) 
     } 
    } 

    private async Task CheckAsync() 
    { 
     if (_running) 
     { 
      return; 
     } 

     _running = true; 

     // await DoworkAsync 
    } 
} 

Startメソッドを非同期に作る必要がある、あなたが

var monitor = new PresenceMonitor(); 
await monitor.Start(); 

の監視を開始することができますあなたも、同期の方法で

var monitor = new PresenceMonitor(); 
monitor.Start(); // Will start monitoring 

の監視を開始することができますが、上記のアプローチは、「危険です"という形で、CheckAsyncメソッド内にスローされた例外は伝播されません。 async-awaitを使用するときは、アプリケーション全体を「変換」してサポートする準備ができていることを確認してください。

+0

あなたはちょうどこの問題を回避しました。 –

+0

@HenkHolterman、 'Start'メソッド実行後のOPのサンプルに基づいて、アプリケーションは毎分CheckAsyncを実行する必要があります。小さな入札でも同じことをより簡単に/読みやすく/維持可能な方法で行います。 OPが彼のアプリケーションで 'async'を使うようになると、彼はとにかく"問題 "で終わり、アプリケーションのすべてのメソッドを"パイプライン "を非同期にします。 – Fabio

+0

はい、そのため、Start()を呼び出さないとこれが完了しません。質問にはどちらも含まれていませんでした。 –

関連する問題