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

VB.NET WinForm创建Ellipse组件类致无响应及VS重启问题排查

问题排查与修复方案

核心崩溃原因:无限递归死循环

你的CornerRedius属性的get/set方法存在致命错误——在get里返回自身,set里赋值自身,这会触发无限递归调用,直接耗尽CPU资源,引发程序无响应甚至Visual Studio崩溃:

Public Property CornerRedius As Integer
    Get
        Return CornerRedius ' 无限调用自身get方法
    End Get
    Set(ByVal value As Integer)
        CornerRedius = value ' 无限调用自身set方法
    End Set
End Property

完整修复后的代码

修复所有问题后的代码如下,包含递归修复、资源释放、事件清理、拼写修正等关键优化:

Imports System.ComponentModel
Imports System.Runtime.InteropServices

Public Class Ellipse
    Inherits Component

    <DllImport("gdi32.dll", EntryPoint:="CreateRoundRectRgn")>
    Private Shared Function CreateRoundRectRgn(ByVal nL As Integer, ByVal nT As Integer, ByVal nR As Integer, ByVal nB As Integer, ByVal nWidthEllipse As Integer, ByVal nHeightEllipse As Integer) As IntPtr
    End Function

    <DllImport("gdi32.dll", EntryPoint:="DeleteObject")>
    Private Shared Function DeleteObject(ByVal hObject As IntPtr) As Boolean
    End Function

    Private _targetControl As Control
    Private _cornerRadius As Integer = 25
    Private _sizeChangedHandler As EventHandler

    Public Property TargetControl As Control
        Get
            Return _targetControl
        End Get
        Set(ByVal value As Control)
            ' 移除旧控件的事件绑定,避免内存泄漏
            If _targetControl IsNot Nothing AndAlso _sizeChangedHandler IsNot Nothing Then
                RemoveHandler _targetControl.SizeChanged, _sizeChangedHandler
            End If

            _targetControl = value
            ' 创建新的事件处理器并绑定
            _sizeChangedHandler = Sub(sender, e) UpdateControlRegion()
            AddHandler _targetControl.SizeChanged, _sizeChangedHandler

            ' 初始化控件圆角区域
            UpdateControlRegion()
        End Set
    End Property

    Public Property CornerRadius As Integer
        Get
            Return _cornerRadius ' 返回私有字段,而非属性自身
        End Get
        Set(ByVal value As Integer)
            ' 过滤无效值,避免重复赋值触发更新
            If value < 0 Then value = 0
            If _cornerRadius <> value Then
                _cornerRadius = value
                UpdateControlRegion()
            End If
        End Set
    End Property

    Private Sub UpdateControlRegion()
        ' 控件未初始化或尺寸无效时跳过更新
        If _targetControl Is Nothing OrElse _targetControl.Width <= 0 OrElse _targetControl.Height <= 0 Then
            Return
        End If

        ' 释放旧区域资源,避免GDI泄漏
        If _targetControl.Region IsNot Nothing Then
            _targetControl.Region.Dispose()
        End If

        ' 创建新圆角区域
        Dim hRgn = CreateRoundRectRgn(0, 0, _targetControl.Width, _targetControl.Height, _cornerRadius, _cornerRadius)
        If hRgn <> IntPtr.Zero Then
            _targetControl.Region = Region.FromHrgn(hRgn)
            ' 释放GDI句柄资源
            DeleteObject(hRgn)
        End If
    End Sub

    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            ' 清理事件绑定和控件区域资源
            If _targetControl IsNot Nothing AndAlso _sizeChangedHandler IsNot Nothing Then
                RemoveHandler _targetControl.SizeChanged, _sizeChangedHandler
            End If
            _targetControl?.Region?.Dispose()
        End If
        MyBase.Dispose(disposing)
    End Sub
End Class

关键修复点说明

  • 解决无限递归:将属性的get/set逻辑指向私有字段_cornerRadius,彻底终止递归循环
  • GDI资源管理:调用DeleteObject释放CreateRoundRectRgn创建的句柄,同时主动释放控件的Region对象,避免资源泄漏
  • 事件绑定清理:更换目标控件时移除旧事件处理器,防止内存泄漏和重复触发更新
  • 输入合法性校验:限制CornerRadius不能为负数,避免创建无效的圆角区域
  • 拼写修正:将错误的CornerRedius修正为标准拼写CornerRadius
  • 边界条件处理:控件尺寸为0时跳过区域更新,避免触发异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:06:34