我正在研究多线程应用程序(服务器),它基本上是一个控制台应用程序。其中我显示处理日志到控制台默认为白色。 但是在成功的交易中我以绿色显示文本,而在不成功的交易中我以红色显示文本。所以我在Program.cs中有三个独立的功能。
简单日志
public static void Write(string text)
{
try
{
Console.Out.Write(text);
}
catch (Exception)
{ }
}
对于不成功的交易,我将颜色更改为红色,然后打印然后再返回白色
public static void WriteError(string text)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("\t" + text);
Console.ForegroundColor = ConsoleColor.White;
}
对于成功的交易,我将颜色更改为绿色,然后打印然后再返回白色
public static void WriteSuccess(string text)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("\t" + text);
Console.ForegroundColor = ConsoleColor.White;
}
问题是连接的客户端超过200个,并且每个客户端的事务日志都在控制台上打印。当我为单行更改颜色如绿色时,它会导致许多其他正常日志行也变为绿色。 所以请告诉我如何解决这个问题。
答案 0 :(得分:14)
如果您的类是唯一一个写入控制台的类,那么锁定一个私有对象(如其他人提到的那样)将起作用。
但是如果还有其他编写者,你还需要与它们同步,否则他们可以在你进入锁定时写入。如果您查看Console
的实现,您会注意到Console.Out
是SyncTextWriter
,它自身同步(使用[MethodImplAttribute(MethodImplOptions.Synchronized)]
)。这意味着如果您将其用作同步对象,您将与其他编写器同步:
lock (Console.Out)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("\t" + text);
Console.ForegroundColor = ConsoleColor.White;
}
如果其他编写者也设置颜色并使用他们自己的同步对象,这仍然无法正常工作。但如果其他作者也在Console.Out
同步,那么它将起作用。
这种方法的问题在于它依赖于实现细节,但我不知道有任何更好的解决方案。
答案 1 :(得分:10)
有你的问题:
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("\t" + text);
您设置颜色,另一个线程中断,将颜色设置为其他颜色,然后打印文本(颜色错误)。
您需要使用锁保护该部分:
static object lockObj = new object();
public static void WriteError(string text)
{
lock(lockObj)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("\t" + text);
Console.ForegroundColor = ConsoleColor.White;
}
}
您必须为WriteSuccess(...)
答案 2 :(得分:1)
使用锁定语句使您的彩色写入原子:
// Only one thread can enter this section at a time
lock(_lockObj)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("\t" + text);
Console.ForegroundColor = ConsoleColor.White;
}
应将_lockObj声明为您的类的私有静态成员:
private static Object _lockObj = new Object();
答案 3 :(得分:0)
您应该使用互斥锁或监视器同步对控制台的访问(某些对象上的lock
会更容易)。