You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

事件触发图片生成时频繁中止线程引发内存泄漏求助

解决线程中止导致的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

关键改动说明

  1. 协作式取消:用CancellationTokenSource替代Thread.Abort(),线程在执行过程中主动检查取消信号,可安全退出,保证Finally块执行,资源必被释放。
  2. 标准Dispose模式:完善Class1的资源释放逻辑,添加终结器兜底,避免因未显式调用Dispose()导致的资源泄漏。
  3. 可靠的资源释放:用Try...Finally块确保Class1的Dispose()一定会被调用,无论线程是正常完成还是被取消。

内容的提问来源于stack exchange,提问作者czxinc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 03:01:40