.NET Framework 4.7遗留系统中存储Thread并检查线程完成状态
解决.NET Framework遗留项目中线程状态检查的问题
核心思路
由于项目无法大规模重构,咱们基于现有Thread实例做最小改动:不需要存储IEnumerable<Thread>引用(容易引发对象生命周期、序列化问题),只需跟踪最后一个线程的状态标识,通过Session实现跨页面状态共享即可。
具体实现步骤
1. 创建线程时初始化状态
在生成Thread实例的类中,启动线程前先在Session中记录线程唯一标识和初始状态,线程执行完毕后更新状态:
C# 示例
// 生成唯一线程ID,避免状态冲突 var threadId = Guid.NewGuid().ToString(); Session["LastWorkerThreadId"] = threadId; Session[$"ThreadCompleted_{threadId}"] = false; var workerThread = new Thread(() => { try { // 原有线程执行的业务逻辑 YourLongRunningMethod(); } finally { // 线程执行完毕,强制更新状态 if (Session != null) { Session[$"ThreadCompleted_{threadId}"] = true; } } }); workerThread.Start();
VB.NET 示例
' 生成唯一线程ID,避免状态冲突 Dim threadId As String = Guid.NewGuid().ToString() Session("LastWorkerThreadId") = threadId Session($"ThreadCompleted_{threadId}") = False Dim workerThread As New Thread(Sub() Try ' 原有线程执行的业务逻辑 YourLongRunningMethod() Finally ' 线程执行完毕,强制更新状态 If Session IsNot Nothing Then Session($"ThreadCompleted_{threadId}") = True End If End Try End Sub) workerThread.Start()
2. 按钮回发时检查状态
在目标页面的按钮点击事件中,读取Session中的状态值,判断最后一个线程是否完成:
C# 示例
protected void CheckThreadStatusBtn_Click(object sender, EventArgs e) { var lastThreadId = Session["LastWorkerThreadId"] as string; if (string.IsNullOrEmpty(lastThreadId)) { lblStatus.Text = "无后台线程执行记录"; return; } var isCompleted = Session[$"ThreadCompleted_{lastThreadId}"] as bool? ?? false; lblStatus.Text = isCompleted ? "最后一个后台线程已完成" : "最后一个后台线程仍在执行"; }
VB.NET 示例
Protected Sub CheckThreadStatusBtn_Click(sender As Object, e As EventArgs) Dim lastThreadId As String = TryCast(Session("LastWorkerThreadId"), String) If String.IsNullOrEmpty(lastThreadId) Then lblStatus.Text = "无后台线程执行记录" Return End If Dim isCompleted As Boolean = If(TryCast(Session($"ThreadCompleted_{lastThreadId}"), Boolean?), False) lblStatus.Text = If(isCompleted, "最后一个后台线程已完成", "最后一个后台线程仍在执行") End Sub
关键注意事项
- 禁止直接存储
Thread实例到Session:Thread是托管资源,无法被正常序列化,且线程结束后实例不会自动释放,容易引发内存泄漏。 - 线程内访问
Session的安全性:后台线程执行时可能遇到用户会话超时,所以加了Session != null的判断,避免空引用异常。 - 可选状态清理:如果需要避免
Session中堆积过期状态,可以在检查完成后,手动清理对应的键值对(比如Session.Remove("LastWorkerThreadId"))。
内容的提问来源于stack exchange,提问作者Nickso
相关产品推荐
相关产品推荐

