3

RichTextBox非UIスレッドがメインスレッドのUIコントロールに出力を追加しようとすると、追跡が難しい例外が発生します。

この例外はランダムな時間に発生します。ほとんどの場合、スレッドがこのメソッドをすばやく連続して呼び出しているときに発生します。UI以外のスレッドが2つしかない場合でも発生します。

以下はAppendLogメソッドのコードです。これは、メインUIのFormクラスにあります。2つのスレッドを生成し、このメソッドを次のように渡します。Action<string> logDelegate

syncobjectも配置しています。

  public void AppendLog(string message)
    {
        try
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<string>(this.AppendLog), message);
            }
            else
            {
                lock (_logSyncRoot)
                {

                    if (rtbLog.TextLength > 100000)
                        rtbLog.ResetText();

                    rtbLog.AppendText(message);
                    rtbLog.ScrollToCaret();
                }
            }
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
        }
    }

System.AccessViolationException:保護されたメモリの読み取りまたは書き込みを試みました。これは多くの場合、他のメモリが破損していることを示しています。

  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.DefWndProc(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.TextBoxBase.WndProc(Message& m)
at System.Windows.Forms.RichTextBox.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.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 MyApp.UI.OfflineAnalyzer.AppendLog(String message) in    D:\MyApp\Code\Charting\OfflineAnalyzer.cs:line 339
4

1 に答える 1

1

このようなシナリオで最も簡単な状況はQueue<string> queue;、たとえばメッセージのリストがある場合にを維持することです。キューに値を自由に追加します。メインフォームスレッドで、タイマーコンポーネントを使用し、値を引き出すときにキューをロックしますlock (queue) {rtbLog.AppendText(queue.Dequeue());}

于 2012-05-09T03:01:38.587 に答える