2017-09-16 36 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()的情况下不完整的原因。这个问题也没有包括在内。 –