如何使用表单textBox使跨线程操作线程安全
本文关键字:线程 操作 安全 何使用 表单 textBox | 更新日期: 2023-09-27 18:26:30
在c#(Visual Studio Express 2013)中,以下代码创建了如下所述的错误:
public void AddToAppLog(string formatter, string loggerId, string logText)
{
lock(this)
{
DateTime dateTime = DateTime.Now;
string logEntry = dateTime.Hour.ToString("00")
+ ":"
+ dateTime.Minute.ToString("00")
+ ":"
+ dateTime.Second.ToString("00")
+ "."
+ dateTime.Millisecond.ToString("000")
+ " [" + loggerId.PadRight(18, '·') + "]" + "> "
+ formatter
+ logText
+ "'n";
applicationLog.AppendText(logEntry);
} // end of lock
} // end of member function: AddToAppLog
错误:
跨线程操作无效:控件"applicationLog"是从创建它的线程以外的线程访问的。
我需要做什么?
使用Control.Invoke
:
applicationLog.Invoke((MethodInvoker)delegate()
{
applicationLog.AppendText(logEntry);
});
代码的问题是,您试图从工作线程设置UI线程拥有的对象的属性,这会导致跨线程异常。
为了在工作线程和UI线程之间正确地进行通信,一种常见的模式是使用Control.Invoke
机制。你需要这样的功能:
private void AppendToAppLog(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (applicationLog.InvokeRequired)
{
this.Invoke(new Action<string>(s => applicationLog.AppendText(s)), text);
}
else
{
applicationLog.AppendText(text);
}
}
然后您可以调用这个函数,而不是示例代码中的AppendText
方法。
AppendToAppLog(logEntry);
此代码确保您可以从UI线程和工作线程附加文本,并且如果不需要(例如,从UI线程调用此方法时),它不会使用Control.Invoke。
下面是一个同时从工作线程和UI线程调用方法的示例:
private void button1_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem((o) => AddToAppLog("", "5215", "Append first"), null);
Task.Factory.StartNew(() => AddToAppLog("", "5215", "Append second"));
AddToAppLog("", "5215", "Append third");
}
以及由此产生的文本框值:
14:26:40.533 [5215··············]> Append third
14:26:40.534 [5215··············]> Append first
14:26:40.554 [5215··············]> Append second