c# - XNA 游戏启动的表单中带有 RichTextBox.ScrollToCaret 的 AccessViolationException

标签 c# .net winforms richtextbox access-violation

我在使用 RichTextBox.ScrollToCaret 时遇到了一些令人沮丧的障碍。我有将消息打印到 RichTextBox 的代码。当每条消息发送到表单时,它被分成多行并格式化,然后连接每行并将结果发送到 RichTextBox.Append。然后,进行以下两个调用以滚动到框的底部:

outputBox.Select(outputBox.Text.Length, 0);
outputBox.ScrollToCaret();

打印一条消息时,没问题。打印少量消息时,没有问题。当快速连续打印一堆消息时,它会随机(在发生之前打印多少条消息)抛出 AccessViolationException(“尝试读取或写入 protected 内存。这通常表明其他内存已损坏。”,full详细信息 here ) 下次在该框中调用追加时添加下一条消息。这种情况在快速连续执行时发生,并且在每次使用 RichTextBox.ScrollToCaret 时发生。我使用的以下代码运行良好:

outputBox.Focus();
outputBox.Select(outputBox.Text.Length, 0);

我还发现,即使我捕获了异常并将其丢弃,程序也会在下次调用 Append 时挂起。所以,我认为这是 RichTextBox 中实际代码的问题。大家有什么想法吗?

如果有人需要,我可以发布更多我的代码,但情况确实非常基本。需要注意的一些事情是,没有多线程(除了固有的 UI 线程之外),因此发送消息的对象和接收消息的表单位于同一线程上。另外,这是在 .NET 4.0 下。

我发现另一个问题解决了这个问题,但只提供了解决方法,没有真正的解释:AccessViolation occurs in RichTextBox.ScrollToCaret 。不幸的是,我在线程方面的经验不是我想要的,所以我无法让他们的解决方案正常工作,但幸运的是我上面发布的内容工作得很好。

更新 1

所以它会进行一些测试,就像它与 XNA 有关,所以这可能是我对其如何与线程一起工作的误解。我无法在纯 WinForms 应用程序中重现该错误,但可以通过简单的 XNA 游戏轻松完成。我把这两本都压缩到这里给你看。对于错误表示歉意。 https://dl.dropbox.com/u/16985121/StackOverFlowExamples.zip

最佳答案

我也遇到了同样的问题。我的情况略有不同,但问题基本相同。我将代码与 C++/CLI 和 C# 形式混合在一起。

来自 C++/CLI 的线程之一调用 C# 形式的函数以将消息打印到 Richtextbox。

“慢慢地”调用这个函数是可以的。但如果调用函数发生得非常快且频繁,程序就会随机崩溃。

这是我的代码。

void PrintOutLog(System::String^ s)
    {
        Monitor::Enter(this->richTextBox_LogBox);
        try
        {
            if(this->richTextBox_LogBox->InvokeRequired)
            {

                AddListItem^ d = gcnew AddListItem(this, &PrintOutLog);
                array<Object^>^ myStringArray = {s};
                this->richTextBox_LogBox->BeginInvoke(d, myStringArray);
            }
            else
            {                
                this->richTextBox_LogBox->AppendText(s + "\n");
                this->richTextBox_LogBox->SelectionStart = this->richTextBox_LogBox->Text->Length;
                this->richTextBox_LogBox->ScrollToCaret();
            }

        }
        finally
        {
            Monitor::Exit(this->richTextBox_LogBox);
        }

    }

事实证明,如果我注释掉以下两行代码,程序就不会再因内存访问冲突而崩溃。

this->richTextBox_LogBox->SelectionStart = this->richTextBox_LogBox->Text->Length;
this->richTextBox_LogBox->ScrollToCaret();

如果我注释掉这两行,那么当 C# 表单没有焦点时,richtextbox 不会在文本框末尾显示新的日志消息。

我可以使用您的解决方案,该解决方案在放置文本之前获得焦点,但如果我这样做,它总是位于我需要保持在最上面的其他窗口的顶部。所以我不能这么做。

我查阅了MSDN页面http://msdn.microsoft.com/en-us/library/system.windows.forms.textboxbase.scrolltocaret.aspx并在页面中间发现这样的内容。

如果控件没有焦点或者插入符号已位于控件的可见区域中,则此方法无效。

但我相信这不是真的。似乎当焦点不在 RichTextBox 控件上时调用 ScrollToCaret() 时,我可以看到 RichTextBox 的滚动条在收到新消息时向下移动,这意味着它打印消息并更新,即使它没有焦点。

我尝试锁定富文本框以免受多线程的影响,但它没有解决访问冲突问题。如果除了使用 focus() 函数之外还有其他解决方案来解决此问题,那就太好了。

谢谢。

关于c# - XNA 游戏启动的表单中带有 RichTextBox.ScrollToCaret 的 AccessViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14027505/

相关文章:

C# MySQLDataReader 在结果中替换

c# - 如何将一个 WinForms 用户控件放在三个窗体上并同时更新所有三个窗体?

c# - 使用反射等效于 default(T)

c# - 如何避免在 .NET Windows 窗体中创建重复的窗体?

c# - 在单声道中编译时 C# List 的问题(与作业相关)

c# - 如何估计 WinForms 中方法的结束时间以正确通知用户预计完成时间?

c# - 尝试解析标记助手指令 '@addTagHelper' 时遇到意外错误

c# - VS2010 代码分析期间的 IDisposable 和 CA2000 警告

c# - 禁用组框时如何更改组框中的字体颜色

c# - 一列中有多个图表区域