我写了一个简单的多线程片段,只是为了让自己习惯这个概念。
public void testThread(int arg1, ConsoleColor color)
{
for (int i = 0; i < 1000; i++)
{
Console.ForegroundColor = color;
Console.WriteLine("Thread " + color.ToString() + " : " + i);
Console.ResetColor();
Thread.Sleep(arg1);
}
}
Thread t1 = new Thread(() => program.testThread(1000, ConsoleColor.Blue));
Thread t2 = new Thread(() => program.testThread(1000, ConsoleColor.Red));
t1.Start();
t2.Start();
t1.Join();
t2.Join();
我在输出控制台窗口中看到的是
我只是不明白为什么有时用红色装饰的线可能会变成白色或浅灰色(无论如何)。你能帮助启发这个想法吗?
提前致谢。
答案 0 :(得分:7)
您的代码块不是 atomic 。这意味着两个线程可以交织在一起。例如:
Thread 1 (Red) Thread 2 (Blue)
--------------------------------------------------------------
Set Color Blue
Set Color Red
Print Text (printed in Red!)
Print Text (printed in Red!)
如果您希望线程的操作是 atomic ,即不间断,则需要使用锁定:
private static readonly object myLock = new object();
public void testThread(int arg1, ConsoleColor color)
{
for (int i = 0; i < 1000; i++)
{
lock (myLock) {
Console.ForegroundColor = color;
Console.WriteLine("Thread " + color.ToString() + " : " + i);
Console.ResetColor();
}
Thread.Sleep(arg1);
}
}
lock statement确保在任何给定时间critical section中只包含一个线程:
Thread 1 (Red) Thread 2 (Blue)
--------------------------------------------------------------
Enter critical section (lock)
wait... Set Color Blue
Print Text (printed in Red!)
Reset Color
Leave critical section
Enter critical section (lock)
...
答案 1 :(得分:5)
由于
Console.ForegroundColor = color;
Console.ResetColor();
Console.WriteLine("Thread " + color.ToString() + " : " + i);
你可以使用锁来防止这种情况发生。
private static readonly object lockObject=new object();
public void testThread(int arg1, ConsoleColor color)
{
for (int i = 0; i < 1000; i++)
{
lock (lockObject) {
Console.ForegroundColor = color;
Console.WriteLine("Thread " + color.ToString() + " : " + i);
Console.ResetColor();
}
Thread.Sleep(arg1);
}
}
Thread t1 = new Thread(() => program.testThread(1000, ConsoleColor.Blue));
Thread t2 = new Thread(() => program.testThread(1000, ConsoleColor.Red));
t1.Start();
t2.Start();
t1.Join();
t2.Join();
答案 2 :(得分:3)
您正在调用Console.ResetColor();
,将颜色设置回默认值(灰色)。因为你有两个线程同时写入控制台,有时一个线程重置之后另一个线程设置它的颜色,但之前另一个线程打印。
您可以使用thread synchronization解决此问题。
答案 3 :(得分:1)
您需要锁定设置控制台颜色的段,直到您打印文本为止。
在打印文本之前,线程可能会中断并重置颜色。
像这样更改你的代码:
public void testThread(int arg1, ConsoleColor color, object lockObj)
{
for (int i = 0; i < 1000; i++)
{
lock(lockObj)
{
Console.ForegroundColor = color;
Console.WriteLine("Thread " + color.ToString() + " : " + i);
Console.ResetColor();
}
Thread.Sleep(arg1);
}
}
var lockObj = new object();
Thread t1 = new Thread(() => program.testThread(1000, ConsoleColor.Blue, lockObj));
Thread t2 = new Thread(() => program.testThread(1000, ConsoleColor.Red, lockObj));