C# Windows服务TCP客户端连接检测及服务停止异常问题咨询
实现合理性相关问题
- 现有实现可正常运行,但存在冗余和隐患
当前线程内启动子线程做心跳检测的设计属于可用但效率不高的方案,为低频次的1分钟心跳任务单独开一个常驻线程,会造成不必要的线程资源浪费,额外增加线程上下文切换开销。
你在两个线程中分别调用client.GetStream()获取的是同一个NetworkStream实例,本身不会创建新连接,但有个隐藏隐患:DoWork方法中你用了using包裹stream,一旦DoWork的逻辑退出using块,stream会被主动释放,此时CheckConnection线程的读写操作会直接抛出运行时异常,你当前未触发问题是因为DoWork中存在阻塞的stream.Read()调用,一直没有退出using块。 - 更优的实现方案
- 心跳检测替换为轻量定时器:使用
System.Threading.Timer实现周期性心跳逻辑,无需占用独立线程,资源开销低很多;如果采用异步重写逻辑,也可以用await Task.Delay()实现心跳间隔,整体代码更简洁。 NetworkStream无需重复获取,共用同一个实例即可:*NetworkStream本身支持读写分离场景下的线程安全,只要保证只有一个线程负责读操作、只有一个线程/定时器负责写操作,不需要额外加锁就可以稳定运行。
- 心跳检测替换为轻量定时器:使用
服务停止卡住问题
该现象属于预期行为,核心原因有两个:
- 你只等待了
_worker线程退出,没有等待CheckConnection线程退出。你创建的Thread默认是前台线程,进程必须等待所有前台线程全部退出才会终止。CheckConnection线程中存在Thread.Sleep(1 * 60 * 1000)的逻辑,_shutdownEvent.Set()之后,线程必须等到1分钟休眠结束才能检测到退出标志,正常退出。 - 阻塞的
stream.Read()被client.Close()唤醒后,会抛出ObjectDisposedException或者IOException,如果你的代码中没有捕获对应异常并正确跳出执行逻辑,会导致_worker线程无法正常退出,Join()无超时的情况下就会一直卡等待。
另外你代码中OnStop方法内调用的是hli_worker.Join(2000),如果该变量和你启动的_worker不是同一个实例,也会导致等待逻辑失效,建议检查变量命名是否一致。
内容的提问来源于stack exchange,提问作者thethakuri
相关产品推荐
相关产品推荐

