我正在开发一款聊天应用.在加载聊天消息并且消息可见5秒后,我想向服务器发送读取确认.这是我到目前为止所提出的:
public async void RefreshLocalData() { // some async code to load the messages if (_selectedChat.countNewMessages > 0) { Device.StartTimer(TimeSpan.FromSeconds(5), SendReadConfirmation); } }
当RefreshLocalData()
被叫时,我知道用户选择了另一个聊天,或者当前聊天中有新消息.因此,当RefreshLocalData()
被调用时,我必须取消当前的计时器以启动一个新计时器.
另一种情况,当我导航到另一个时,我必须取消计时器Page
.这没有问题,因为ViewModel
当发生这种情况时整个都被处理掉了.
使用上面的代码,如果RefreshLocalData()
再次调用if 但是TimeSpan
5秒的声明尚未结束,则该方法仍在执行.
有没有办法取消计时器(如果RefreshLocalData()
再次调用)?
我在Xamarin论坛中找到了这个答案:https://forums.xamarin.com/discussion/comment/149877/#Comment_149877
我已经改变了一点以满足我的需求,这个解决方案正在起作用:
public class StoppableTimer { private readonly TimeSpan timespan; private readonly Action callback; private CancellationTokenSource cancellation; public StoppableTimer(TimeSpan timespan, Action callback) { this.timespan = timespan; this.callback = callback; this.cancellation = new CancellationTokenSource(); } public void Start() { CancellationTokenSource cts = this.cancellation; // safe copy Device.StartTimer(this.timespan, () => { if (cts.IsCancellationRequested) return false; this.callback.Invoke(); return false; // or true for periodic behavior }); } public void Stop() { Interlocked.Exchange(ref this.cancellation, new CancellationTokenSource()).Cancel(); } public void Dispose() { } }
这就是我在RefreshLocalData()
方法中使用它的方式:
private StoppableTimer stoppableTimer; public async void RefreshLocalData() { if (stoppableTimer != null) { stoppableTimer.Stop(); } // some async code to load the messages if (_selectedChat.countNewMessages > 0) { if (stoppableTimer == null) { stoppableTimer = new StoppableTimer(TimeSpan.FromSeconds(5), SendReadConfirmation); stoppableTimer.Start(); } else { stoppableTimer.Start(); } } }