【发布时间】:2019-10-04 13:48:12
【问题描述】:
我继承了一些旧代码,在我看来它的某些部分存在问题。
该程序使用 TCP/IP 与另一个程序通信,协议简单。发送命令电报并等待响应电报。
这是我认为有问题的部分。
public System.Timers.Timer retransmitTimer;
public TelegramBase SendAndWait(TelegramBase telegram)
{
CurrentTelegram = telegram;
retransmitTimer = new Timer(RetransmitInterval);
retransmitTimer.Elapsed += retransmitTimer_Elapsed;
//Send telegram
Send(telegram);
//Start timer
retransmitTimer.Start();
//Wait for response
var response = WaitForResponse(telegram as StandardTelegram);
//stop timer
retransmitTimer.Stop();
return response;
}
每次发送命令电报时都会调用方法 SendAndWait。
我的问题是计时器的创建
retransmitTimer = new Timer(RetransmitInterval);
retransmitTimer.Elapsed += retransmitTimer_Elapsed;
这将创建一个新的计时器,但当前的计时器从未被释放,所以它会继续运行?最好的情况是停止。
什么更好?
- 将计时器的创建移到只调用一次的方法中?
- 释放当前计时器,然后在 SendAndWait 中创建一个新计时器?
【问题讨论】:
-
你不需要计时器。使用带有超时的CancellationToken。
-
"所以它将继续运行" 这是一个问题还是一个声明?你试过了吗?你还会收到旧计时器触发的事件吗?
-
@HimBromBeere 这主要是一个问题,但是是的,有时会有旧计时器触发的事件。
-
唯一真正关键的细节是计时器需要停止,所以他应该将 Stop() 调用放在 finally 块中以确保它是异常安全的。当您正确使用 using 语句时,您当然会自动获得它。您应该更担心的是即使收到响应,当计时器滴答时会发生什么。这很可能是您无法为 System.Timers.Timer 修复的线程竞争错误。只要确保它发生时不会爆炸。