添加Redis后VB.NET程序运行数小时出现System.StackOverflowException
解决System.StackOverflowException的方案
首先咱们拆解下你的代码里几个可能导致栈溢出的核心问题,再一步步给出修复方案:
问题根源分析
运行3-4小时后触发System.StackOverflowException,主要和以下两点有关:
- 低效的字符串拼接:
TextBox1.Text += command每次都会生成新的字符串对象(.NET里字符串是不可变的),长时间运行后字符串会变得异常庞大,赋值到TextBox时会带来额外的栈/内存压力;同时频繁创建新对象会加重GC负担,间接引发栈溢出。 - 空Catch块吞掉异常:当
db.ListRightPop("command")返回null时,调用ToString()会抛出NullReferenceException,但你的空Catch块直接吞掉了所有异常——这些未处理的异常在后台反复积累,最终可能触发栈溢出。 - 潜在的跨线程问题:如果你的定时器用的是
System.Timers.Timer(非UI线程定时器),直接访问TextBox1.Text属于跨线程操作,会抛出异常,即使被吞掉,多次触发也可能导致内部栈堆积。
修复后的代码示例
' 全局变量保留,新增StringBuilder用于高效拼接字符串 Dim redis As ConnectionMultiplexer = ConnectionMultiplexer.Connect("127.0.0.1") Dim db As IDatabase = redis.GetDatabase() Dim sb As New StringBuilder() Dim updateCounter As Integer = 0 ' 控制UI更新频率的计数器 ' 定时器任务修改为: Try Dim commandObj As Object = db.ListRightPop("command") ' 先判断是否为null,避免ToString()抛出空引用异常 If commandObj IsNot Nothing Then Dim command As String = commandObj.ToString() Console.WriteLine(command.Length) ' 用StringBuilder拼接,避免频繁创建新字符串 sb.Append(command) ' 每10次触发再更新一次UI,减少UI线程负担 updateCounter += 1 If updateCounter >= 10 Then ' 处理跨线程访问UI的情况(如果用的是非UI定时器) If TextBox1.InvokeRequired Then TextBox1.Invoke(Sub() TextBox1.Text = sb.ToString()) Else TextBox1.Text = sb.ToString() End If updateCounter = 0 End If End If Catch ex As Exception ' 不要吞掉异常,记录下来方便排查问题 Console.WriteLine($"定时器任务异常:{ex.ToString()}") End Try
额外优化建议
- 控制UI更新频率:如果定时器每秒触发多次,没必要每次都更新TextBox,像上面那样每10次更新一次,能大幅降低UI线程的压力。
- 监控Redis操作:可以在日志里记录每次
ListRightPop的结果,确认是否有异常数据(比如超长字符串)导致问题。 - 复用ConnectionMultiplexer:你当前的全局变量定义是对的,
ConnectionMultiplexer是单例设计,不要频繁创建新实例,避免连接资源浪费。
内容的提问来源于stack exchange,提问作者dan dadadadan
相关产品推荐
相关产品推荐

