事件触发图片生成时频繁中止线程引发内存泄漏求助
解决线程中止导致的Bitmap内存泄漏问题
问题根源
Thread.Abort()是强制中止线程,不可控性极强:当线程在Class1构造函数执行过程中被中止时,newObj可能还未完成初始化(仍为Nothing),导致Catch块里的Dispose()无法触发,Bitmap持有的非托管资源得不到释放,直接引发内存泄漏。GC.Collect()无效是因为未释放的Bitmap包含非托管资源,只有显式调用Dispose()释放这些资源后,GC才能回收对应的托管对象。- 定时器间隔增大后泄漏变慢,本质是线程有更多时间完成构造和资源释放,被强制中止的概率降低。
解决方案
放弃Thread.Abort()的强制中止方式,改用协作式取消机制,让线程主动响应取消信号,同时通过标准的资源释放模式确保资源不泄漏。
修正后的代码
Imports System.Threading Public Class Form1 Dim cts As CancellationTokenSource Dim workerThread As Thread Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick RestartImageGeneration() End Sub Sub RestartImageGeneration() ' 取消当前任务并等待线程结束 If cts IsNot Nothing AndAlso Not cts.IsCancellationRequested Then cts.Cancel() workerThread?.Join() cts.Dispose() End If ' 启动新的图片生成线程 cts = New CancellationTokenSource() workerThread = New Thread(AddressOf GenerateImage) workerThread.Start(cts.Token) End Sub Sub GenerateImage(token As CancellationToken) Dim imageGenerator As Class1 = Nothing Try imageGenerator = New Class1() ' 模拟图片生成逻辑,过程中主动检查取消信号 For i As Integer = 0 To 1000 If token.IsCancellationRequested Then Exit For End If Thread.Sleep(10) ' 替换为你的实际图片生成代码 Next Finally ' 无论任务正常完成还是被取消,都确保资源释放 imageGenerator?.Dispose() End Try End Sub End Class Public Class Class1 Implements IDisposable Private img As Bitmap Private disposedValue As Boolean Public Sub New() img = New Bitmap(4095, 4095) End Sub Protected Overridable Sub Dispose(disposing As Boolean) If Not disposedValue Then If disposing Then ' 释放托管资源 img?.Dispose() End If ' 清理非托管资源引用 img = Nothing disposedValue = True End If End Sub Public Sub Dispose() Implements IDisposable.Dispose Dispose(disposing:=True) GC.SuppressFinalize(Me) End Sub ' 终结器:兜底处理未显式调用Dispose的情况 Protected Overrides Sub Finalize() Try Dispose(disposing:=False) Finally MyBase.Finalize() End Try End Sub End Class
关键改动说明
- 协作式取消:用
CancellationTokenSource替代Thread.Abort(),线程在执行过程中主动检查取消信号,可安全退出,保证Finally块执行,资源必被释放。 - 标准Dispose模式:完善
Class1的资源释放逻辑,添加终结器兜底,避免因未显式调用Dispose()导致的资源泄漏。 - 可靠的资源释放:用
Try...Finally块确保Class1的Dispose()一定会被调用,无论线程是正常完成还是被取消。
内容的提问来源于stack exchange,提问作者czxinc
相关产品推荐
相关产品推荐

