2017-09-16 37 views
0

我有一個存在監視器類用於檢測用戶活動/非活動狀態。這個類在它的啓動方法,要求在應用程序啓動一個定時器:異步等待不起作用定時器

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 
    } 
} 

「檢查」的方法是每隔一分鐘後被解僱。這一段代碼工作正常,但現在我的「做工作」的方法已成爲異步等待,所以我不得不這種存在監控類更改爲這樣的事情:

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」方法現在被解僱了一次而不是每分鐘。你能告訴我我在做什麼錯在這裏調用async等待定期後?

有沒有正確的方法來做同樣的事情?

+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

它應該是「私人異步任務DoworkAsync(),對嗎? – Raghav

+0

@Raghav,只有當你在該方法中使用'await'時,我不知道該方法是什麼樣子,所以它取決於它是如何實現的 – Nkosi

0

如果我理解正確,您的要求,您可以擺脫計時器和使用異步循環。
但你需要做Start方法異步太

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 
    } 
} 

然後你就可以開始監測

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

你甚至可以開始監測同步方式

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

但上述做法是「危險的「順便說一下,CheckAsync方法中拋出的任何異常都不會被傳播。當你開始使用async-await準備好「轉換」整個應用程序來支持它。

+0

你剛剛解決了這個問題。對Start()的調用已經變成異步,你不知道是否/如何解決這個問題。 –

+0

@HenkHolterman,基於OP的例子,執行'Start'方法後,應用程序應該每分鐘運行一次'CheckAsync'。將以更簡單/可讀/可維護的方式在小投標中完成同樣的事情。如果OP在他的應用程序中開始使用'async',他將最終以「問題」結束,以使所有的應用程序「管道」異步。 – Fabio

+0

是的,這就是沒有調用Start()的情況下不完整的原因。這個問題也沒有包括在內。 –