我有一个由其他主线程处理的计时器,但似乎计时器没有被处理,并且即使在那之后回调正在执行。在代码中我连续轮询语音校准状态然后再次重新初始化计时器
这是代码段:
private void check_voice_call_State_cb(object obj)
{
Voice_call_state_timer.Dispose();
outputdata = SystemUtil.trace_proc(OnlineData.ADB_PATH, "-s " +
OnlineData.ADB_serial[PhoneNum] + @" shell ""dumpsys
telephony.registry | grep mCallState""");
Voice_call_state_timer = new System.Threading.Timer(
check_voice_call_State_cb,
this,
2000,
System.Threading.Timeout.Infinite);
}
答案 0 :(得分:0)
来自MSDN Documentation for the class
当不再需要计时器时,使用Dispose方法释放计时器持有的资源。请注意,在调用Dispose()方法重载之后可能会发生回调,因为定时器会将回调排队以供线程池线程执行。您可以使用Dispose(WaitHandle)方法重载等待所有回调完成。
因此,您需要使用其他重载来等待所有回调完成。
private void check_voice_call_State_cb(object obj)
{
using(var handle = new ManualResetEvent(false))
{
var disposed = Voice_call_state_timer.Dispose(handle);
if(!disposed)
{
//This is a extra firing of the event, we should not process further.
return;
}
handle.WaitOne(); //Wait for the dispose to finish here.
}
outputdata = SystemUtil.trace_proc(OnlineData.ADB_PATH, "-s " +
OnlineData.ADB_serial[PhoneNum] + @" shell ""dumpsys
telephony.registry | grep mCallState""");
Voice_call_state_timer = new System.Threading.Timer(
check_voice_call_State_cb,
this,
2000,
System.Threading.Timeout.Infinite);
}
然而,更好的解决方案是使用标志来检测多个呼叫,然后只需调用Change
来设置计时器关闭的新时间。与重复创建和处理计时器相比,这使用的资源要少得多。
var timerSemaphore = new SemaphoreSlim(1)
private void check_voice_call_State_cb(object obj)
{
var gotLock = timerSemaphore.Wait(0);
if(!gotLock)
{
//Another instance of the timer callback is running, just return.
return;
}
try
{
outputdata = SystemUtil.trace_proc(OnlineData.ADB_PATH, "-s " +
OnlineData.ADB_serial[PhoneNum] + @" shell ""dumpsys
telephony.registry | grep mCallState""");
//Move this to inside the finally bock to make this happen even on a exception.
Voice_call_state_timer.Change(2000, System.Threading.Timeout.Infinite);
}
finally
{
timerSemaphore.Release();
}
}