C#:线程安全的richtextbox事件记录方法?

我有一个方法,用于在表单中的RichTextBox上显示输出。

public void LogTextEvent(RichTextBox TextEventLog, Color TextColor, string EventText) { string nDateTime = DateTime.Now.ToString("hh:mm:ss tt") + " - "; // color text. TextEventLog.SelectionStart = TextEventLog.Text.Length; TextEventLog.SelectionColor = TextColor; // newline if first line, append if else. if (TextEventLog.Lines.Length == 0) { TextEventLog.AppendText(nDateTime + EventText); TextEventLog.ScrollToCaret(); TextEventLog.AppendText(System.Environment.NewLine); } else { TextEventLog.AppendText(nDateTime + EventText + System.Environment.NewLine); TextEventLog.ScrollToCaret(); } } 

当我从线程内运行的另一个方法调用LogEventText()时出现问题:

  Thread thListening = new Thread(new ThreadStart(StartListening)); thListening.Start(); 

在StartListening方法内部(它是一个创建的线程,用于处理为小型http服务器的主侦听套接字上的客户端创建的新tcp套接字),我使用LogTextEvent来记录一些数据,但是我收到InvalidOperationException是未处理的错误在第二行的LogTextEvent方法中,TextEventLog.SelectionStart = TextEventLog.Text.Length;

错误读取,跨线程操作无效:控制’rchEventLog’从其创建的线程以外的线程访问。

任何人都可以帮助分解正在发生的事情,为什么以及如何修复错误?

尝试这样的事情:

 public void LogTextEvent(RichTextBox TextEventLog, Color TextColor, string EventText) { if (TextEventLog.InvokeRequired) { TextEventLog.BeginInvoke(new Action(delegate { LogTextEvent(TextEventLog, TextColor, EventText); })); return; } string nDateTime = DateTime.Now.ToString("hh:mm:ss tt") + " - "; // color text. TextEventLog.SelectionStart = TextEventLog.Text.Length; TextEventLog.SelectionColor = TextColor; // newline if first line, append if else. if (TextEventLog.Lines.Length == 0) { TextEventLog.AppendText(nDateTime + EventText); TextEventLog.ScrollToCaret(); TextEventLog.AppendText(System.Environment.NewLine); } else { TextEventLog.AppendText(nDateTime + EventText + System.Environment.NewLine); TextEventLog.ScrollToCaret(); } } 

如果从富文本框的UI线程以外的线程调用LogTextEvent方法,它将向UI线程发布消息,这将导致在该线程中调用LogTextEvent方法。

通过使用BeginInvoke而不是Invoke,它是异步发布的,这意味着它会立即返回给调用者,而不是等待在另一个线程上执行该方法。 对于像这样的日志记录方案,这可能是您想要的。 如果你需要从控件或某些东西获取一个值,你可能需要使用Invoke。

 new Thread(new ThreadStart(delegate { //do some worker-thread processing here ... //now update the gui from within the gui thread MyRichTextBox.Invoke(new Action(delegate { MyRichTextBox.SelectionStart = CalculateTheSelectionStart(); })); })).Start();