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 メソッド/プロパティが使用される 3 回のうちの 1 つになります。常に例外がスローされるとは限りません。時々物が凍るように見えます。ただし、メインの UI ではなく、メッセージの流れだけです (つまり、ログは二度と呼び出されないように見えます)。

アプリは、バックグラウンド プロセスを備えた単一のフォームです。私はこれで何が間違っているのかわかりません...

更新

私は Mangist の提案を行います。これがコードです (タイマーは 100ms で起動します)。同じ結果:

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 に答える