1

我有一堆背景事件。

他们都调用了一个日志:

private void log(string text, params object[] values)
{
    if (editLog.InvokeRequired)
    {
        editLog.BeginInvoke(
            (MethodInvoker)delegate
            {
                this.log(text, values);
            });
    }
    else
    {
        text = string.Format(text, values) + Environment.NewLine;

        lock (editLog)
        {
            editLog.AppendText(text);
            editLog.SelectionStart = editLog.TextLength;
            editLog.ScrollToCaret();               
        }
    }
}

有时我得到这个,但其他时候没有:

System.AccessViolationException was unhandled
  Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
  Source=System.Windows.Forms
  StackTrace:
       at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
       at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.RichTextBox.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, Int32 wParam, Object& editOle)
       at System.Windows.Forms.TextBoxBase.ScrollToCaret()
       at Program1.frmMain.log(String text, Object[] values) in 
       ...
       ...
       ...

PD:并不总是停在这一行,随机将是使用 editLog 方法/属性的三次之一。并不总是抛出异常。有时看起来像东西冻结。但不是主 UI,只是消息流(即:日志看起来不再被调用)

该应用程序是单一表单,具有后台进程。我看不出我做错了什么...

更新

我按照 Mangist 的建议,这是代码(定时器在 100 毫秒触发)。结果相同:

private Queue<String> logs = new Queue<String>();
private void timerLog_Tick(object sender, EventArgs e)
{
    lock (logs)
    {
        for (int i = 0; i < logs.Count; i++)
        {
            editLog.AppendText(logs.Dequeue());
            editLog.SelectionStart = editLog.TextLength;
            editLog.ScrollToCaret();
        }             
    }
}

private void log(string text, params object[] values)
{
    text = string.Format(text, values) + Environment.NewLine;

    if (editLog.InvokeRequired)
    {
        editLog.BeginInvoke(
            (MethodInvoker)delegate
            {
                lock (logs)
                {
                    logs.Enqueue(text);
                }
                //this.log(text, values);
            });
    }
    else
    {
        logs.Enqueue(text);
    }
}
4

2 回答 2

1

如果日志记录启动得非常快(在创建表单句柄之前),就会发生这种情况。editLog.IsHandleCreated == true在调用控件上的任何方法之前检查。这会有所帮助,否则使用线程安全Queue<string>(用lock (obj) {}语句包围)并在表单中放置一个计时器以定期读取此队列以获取新日志。

于 2012-06-25T21:12:05.930 回答
0

嗯,终于找到问题了。删除它可以消除问题(并使用正常的 BeginInvoke,没有技巧、锁等):

editLog.SelectionStart = editLog.TextLength;
editLog.ScrollToCaret();

我尝试使用http://nlog-project.org/并且我的第一次尝试工作完全正常(使用http://nlog-project.org/wiki/RichTextBox_target)。当我设置时 autoScroll="true"再次得到相同的错误。这就是我发现问题的方式。

于 2012-06-26T21:50:38.237 回答