繁体   English   中英

更改控制台颜色在多线程应用程序中不能正常工作

[英]Changing console color not working exactly in multithreaded applications

我正在研究多线程应用程序(服务器),它基本上是一个控制台应用程序。 其中我显示处理日志到控制台默认为白色。 但是在成功的交易中我以绿色显示文本,而在不成功的交易中我以红色显示文本。 所以我在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个,并且每个客户端的事务日志都在控制台上打印。 当我为单行更改颜色如绿色时,它会导致许多其他正常日志行也变为绿色。 所以请告诉我如何解决这个问题。

如果您的类是唯一写入控制台的类,则锁定单个私有对象(如其他人提到的那样)将起作用。

但是如果有其他编写器,你还需要与它们同步,否则它们可能会在你进入锁定时写入。 如果查看Console的实现,您会注意到Console.Out是一个SyncTextWriter ,它自身同步(使用[MethodImplAttribute(MethodImplOptions.Synchronized)] )。 这意味着如果您将其用作同步对象,您将与其他编写器同步:

lock (Console.Out)
{
    Console.ForegroundColor = ConsoleColor.Green;
    Console.WriteLine("\t" + text);
    Console.ForegroundColor = ConsoleColor.White;
}

如果其他编写者也设置颜色并使用他们自己的同步对象,这仍然无法正常工作。 但如果其他编写者也在Console.Out同步,它将起作用。

这种方法的问题在于它依赖于实现细节,但我不知道有任何更好的解决方案。

有你的问题:

    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(...)做同样的事情

使用lock语句使您的彩色写入原子:

// 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();

您应该使用Mutex或监视器同步对控制台的访问( lock某些对象会更容易)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM