2012-06-25 40 views
1

我有一堆後臺事件。Winforms:試圖讀取或寫入受保護的內存。這通常表示其他內存已損壞

所有這些調用日誌:

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方法/屬性。拋出並不總是一個例外。有時看起來像事情凍結。但不是主界面,只是消息流(即:日誌看起來像是再也不會被調用)

該應用程序是一種具有後臺進程的單一表單。我看不出有什麼我做錯了這個...

UPDATE

我做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); 
    } 
} 
+0

在UI線程中鎖定控件的目的是什麼?您已經保證通過消息泵進行單線程訪問。 –

+0

那麼,那個鎖是我猜想的部分... – mamcx

+1

Asa一般規則:*永遠不會*鎖定一個真實的物體(例如'this')。總是使用'new object()'成員來進行鎖定。請參閱[爲什麼偉大的想法不是那麼偉大](http://msdn.microsoft.com/en-us/magazine/cc188793.aspx#S7) –

回答

1

如果日誌記錄啓動非常快(在創建表格句柄之前),可能會發生這種情況。在調用控件上的任何方法之前檢查editLog.IsHandleCreated == true。這可以提供幫助,否則使用線程安全的Queue<string>(用lock (obj) {}語句包圍)並在表單中放置一個計時器以定期讀取此隊列中的新日誌。

+0

我實現了兩個,仍然遇到同樣的問題。 – mamcx

+0

在追加文本之前添加對editLog.IsHandleCreated == true的檢查。 – Mangist

+0

仍是同樣的問題。即使GUI凍結:( – mamcx

0

好了,終於找到了問題。刪除此消除此問題(並與正常BeginInvoke的工作,沒有技巧,鎖和):

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

我嘗試使用http://nlog-project.org/和我第一次學嘗試的工作completelly OK(帶http://nlog-project.org/wiki/RichTextBox_target)。當我設置autoScroll="true"時再次得到相同的錯誤。這是我如何找到問題。

相關問題