using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MultiThreadLog
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
for (int i = 0; i < 5; i++)
{
Task.Factory.StartNew(() => {
string str = System.DateTime.Now.ToString("fff");
Debug.WriteLine(str);
Log(str);
});
}
}
void Log(string content)
{
this.txtLog.Text += System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":" + content + "\r\n";
this.txtLog.Focus();
this.txtLog.Select(this.txtLog.TextLength, 0);
this.txtLog.ScrollToCaret();
}
}
}
嗨,有时候,在txtLog中,有4行,应该是5行。有谁知道为什么? 非常感谢............................................... .................................................. ................
答案 0 :(得分:4)
您的代码首先出现的问题是这一行:
20170822-13:56:02 : 50 ms
20170822-13:56:03 : 36 ms
20170822-13:56:03 : 59 ms
20170822-13:56:03 : 40 ms
20170822-13:56:03 : 67 ms
这种例外是有原因的。它可以帮助您避免编写错误的代码,即从拥有该对象的线程以外的线程访问UI对象的代码。不要那样做。
你的代码出现问题的另一个问题是这一行:
Control.CheckForIllegalCrossThreadCalls = false;
同时执行该行的两个不同线程可以(并且在您的情况下)同时检索this.txtLog.Text += System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":" + content + "\r\n";
的当前值,将其新文本连接到该文本,然后将结果重新分配给{{ 1}}。无论哪个线程重新分配最后的胜利,都要覆盖先前线程(或多个线程)试图写入的内容。
如果您使用Text
更新UI(即调用Text
方法),那么所有代码将被强制回到它所属的UI线程,您的竞争条件将是在UI线程内原子地解决,防止这种并发访问错误。 E.g:
Control.Invoke()
答案 1 :(得分:0)