【发布时间】:2012-06-27 03:36:55
【问题描述】:
我有一堆背景事件。
他们都调用了一个日志:
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
...
...
...
P.D:并不总是停在这一行,随机将是使用 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);
}
}
【问题讨论】:
-
在 UI 线程中锁定控件的目的是什么?消息泵已经保证您可以单线程访问。
-
嗯,那把锁在我看来纯属猜测......
-
一般规则:从不锁定真实对象(例如
this)。始终使用new object()成员仅用于锁定。见Why the Great Idea isn't So Great
标签: .net winforms multithreading visual-studio-2008 .net-4.0