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
相关产品推荐
相关产品推荐

