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

C#程序特定代码段运行时关闭窗口触发RichTextBox已释放对象异常求助

问题原因分析

点击窗口关闭按钮时,窗体开始释放内部控件(包括tbDisplayText这个RichTextBox),但你的异步循环仍在执行——await Task.Delay(speed)之后,代码会尝试访问已经被Dispose的tbDisplayText,这就触发了ObjectDisposedException。其他场景下关闭窗口时没有这个循环在运行,所以不会报错。

解决方法

以下是几种直接可行的修复方案:

方案1:添加关闭标志位检查

  1. 在窗体类中定义私有字段:
private bool _isFormClosing;
  1. 重写窗体的OnFormClosing方法:
protected override void OnFormClosing(FormClosingEventArgs e)
{
    _isFormClosing = true;
    base.OnFormClosing(e);
}
  1. 修改循环代码,每次操作控件前检查标志位:
while (firstColorChange < lines.Length + numTextLength.Value)
{
    if (_isFormClosing) break;

    if (firstColorChange < lines.Length)
    {
        if (_isFormClosing) break;
        tbDisplayText.Select(firstColorChange, 1);
        tbDisplayText.SelectionColor = Color.Red;
        firstColorChange++;
    }
    
    if (firstColorChange > numTextLength.Value)
    {
        if (_isFormClosing) break;
        tbDisplayText.Select(secondColorChange, 1);
        tbDisplayText.SelectionColor = Color.White;
        secondColorChange++;
    }

    await Task.Delay(speed);
    if (_isFormClosing) break;

    if(secondColorChange == lines.Length)
    {
        if (!_isFormClosing) tbDisplayText.Clear();
        break;
    }
}

方案2:直接检查控件的IsDisposed属性

每次操作tbDisplayText前,判断它是否已被释放:

while (firstColorChange < lines.Length + numTextLength.Value)
{
    if (tbDisplayText.IsDisposed) break;

    if (firstColorChange < lines.Length)
    {
        if (tbDisplayText.IsDisposed) break;
        tbDisplayText.Select(firstColorChange, 1);
        tbDisplayText.SelectionColor = Color.Red;
        firstColorChange++;
    }
    
    if (firstColorChange > numTextLength.Value)
    {
        if (tbDisplayText.IsDisposed) break;
        tbDisplayText.Select(secondColorChange, 1);
        tbDisplayText.SelectionColor = Color.White;
        secondColorChange++;
    }

    await Task.Delay(speed);
    if (tbDisplayText.IsDisposed) break;

    if(secondColorChange == lines.Length)
    {
        if (!tbDisplayText.IsDisposed) tbDisplayText.Clear();
        break;
    }
}

方案3:使用CancellationToken(规范的异步取消方式)

  1. 在窗体类中定义CancellationTokenSource:
private CancellationTokenSource _cts;
  1. 启动循环前初始化令牌:
_cts = new CancellationTokenSource();
// 调用循环方法时传入_cts.Token
  1. 修改循环方法,接收CancellationToken:
async Task UpdateTextColors(CancellationToken token)
{
    while (firstColorChange < lines.Length + numTextLength.Value && !token.IsCancellationRequested)
    {
        if (firstColorChange < lines.Length && !token.IsCancellationRequested)
        {
            tbDisplayText.Select(firstColorChange, 1);
            tbDisplayText.SelectionColor = Color.Red;
            firstColorChange++;
        }
        
        if (firstColorChange > numTextLength.Value && !token.IsCancellationRequested)
        {
            tbDisplayText.Select(secondColorChange, 1);
            tbDisplayText.SelectionColor = Color.White;
            secondColorChange++;
        }

        try
        {
            await Task.Delay(speed, token);
        }
        catch (OperationCanceledException)
        {
            break;
        }

        if(token.IsCancellationRequested) break;

        if(secondColorChange == lines.Length)
        {
            tbDisplayText.Clear();
            break;
        }
    }
}
  1. 在FormClosing事件中取消令牌:
protected override void OnFormClosing(FormClosingEventArgs e)
{
    _cts?.Cancel();
    _cts?.Dispose();
    base.OnFormClosing(e);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:11:07