14

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

4

4 回答 4

21

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

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

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

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

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

于 2015-08-14T14:01:09.870 回答
12

有你的问题:

    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(...)

于 2012-12-13T14:03:37.110 回答
1

使用 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();
于 2012-12-13T14:07:39.977 回答
0

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

于 2012-12-13T14:06:02.767 回答