在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
错误:
跨线程操作无效:Control' applicationLog'从创建它的线程以外的线程访问。
我需要做什么?
答案 0 :(得分:2)
applicationLog.Invoke((MethodInvoker)delegate()
{
applicationLog.AppendText(logEntry);
});
答案 1 :(得分:1)
您的代码的问题在于您尝试从工作线程设置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线程和工作线程附加文本,如果不需要,它将不使用Control.Invoke(例如,从UI线程调用此方法时)。
以下是从工作线程和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