使用Console.Writeline()或Console.Write()时,多线程C#控制台应用程序中偶尔会挂起

Gor*_*rgh 10 c# console-application console.writeline hang

我编写了一个控制台应用程序,它使用console.write和console.writeline来提供一些日志记录.该应用程序是一个服务器应用程序,它使用异步beginacceptconnection()和beginread()(套接字)进行通信.偶尔我会得到挂起的报告,从有限的调试我可以做到,我能够看到问题是Console.Writeline()或Console.write().

作为多线程我一直小心锁定日志记录类,所以只有一个线程可以一次记录消息.....当我抓到一个挂起所有我得到的是线程阻塞锁和VS报告控件已经传递到Console.Write,它正在等待它回来....它永远不会.

几天前我得到了另一个失败的报告,但这次是在启动时....没有asynch连接尚未启动(主线程确实产生了一个线程启动),我被发送了一张图片.. ...见下文.(我添加了开始和结束关键部分线以防止这种情况,但它没有)

// Logging Class

public class Logging
{
    // Lock to make the logging class thread safe.
    static readonly object _locker = new object();

    public delegate void msgHandlerWriteLineDelegate(string msg, Color col);
    public static event msgHandlerWriteLineDelegate themsgHandlerWriteLineDelegate;

    public delegate void msgHandlerWriteDelegate(string msg, Color col);
    public static event msgHandlerWriteDelegate themsgHandlerWriteDelegate;

    public static void Write(string a, Color Col)
    {
        if (themsgHandlerWriteDelegate != null)
        {
            lock (_locker)
            {
                themsgHandlerWriteDelegate(a, Col);
            }
        }
    }

    public static void Write(string a)
    {
        if (themsgHandlerWriteDelegate != null)
        {
            lock (_locker)
            {
                themsgHandlerWriteDelegate(a, Color.Black);
            }
        }
    }

    public static void WriteLine(string a, Color Col)
    {
        if (themsgHandlerWriteLineDelegate != null)
        {
            lock (_locker)
            {
                themsgHandlerWriteLineDelegate(a, Col);
            }
        }
    }

    public static void WriteLine(string a)
    {
        if (themsgHandlerWriteLineDelegate != null)
        {
            lock (_locker)
            {
                themsgHandlerWriteLineDelegate(a, Color.Black);
            }
        }
    }

    // Console Methods That implement the delegates in my logging class.

    public static void ConsoleWriteLine(string message, Color Col)
    {
        try
        {
            if (Col == Color.Black)
            {
                Console.ForegroundColor = ConsoleColor.Gray;
            }
            else
            {
                Console.ForegroundColor = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), Col.Name);
            }
            Thread.BeginCriticalRegion();
            Console.WriteLine(message);
            Thread.EndCriticalRegion();
            Console.ForegroundColor = ConsoleColor.Gray;
        }
        catch (ThreadAbortException ex)
        {
            Console.WriteLine("ThreadAbortException : " + ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception : " + ex.Message);
        }
    }

    public static void ConsoleWrite(string message, Color Col)
    {
        try
        {
            if (Col == Color.Black)
            {
                Console.ForegroundColor = ConsoleColor.Gray;
            }
            else
            {
                Console.ForegroundColor = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), Col.Name);
            }
            Thread.BeginCriticalRegion();
            Console.Write(message);//**THIS IS WHERE IS HANGS...IT NEVER RETURNS **
            Thread.EndCriticalRegion();
            Console.ForegroundColor = ConsoleColor.Gray;
        }
        catch (ThreadAbortException ex)
        {
            Console.WriteLine("ThreadAbortException : " + ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception : " + ex.Message);
        }
    }

    public static void ConsoleUpdate(string message)
    {
        try
        {
            Thread.BeginCriticalRegion();
            Console.WriteLine(message);//**THIS IS WHERE IS HANGS...IT NEVER RETURNS **
            Thread.EndCriticalRegion();
        }
        catch (ThreadAbortException ex)
        {
            Console.WriteLine("ThreadAbortException : " + ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception : " + ex.Message);
        }
    }

    // The main method...subscribes to delegates and spawns a thread to boot HW..main thread then exits.

    public static void Main()
    {
        Logging.themsgHandlerWriteDelegate += new Logging.msgHandlerWriteDelegate(ConsoleWrite);
        Logging.themsgHandlerWriteLineDelegate += new Logging.msgHandlerWriteLineDelegate(ConsoleWriteLine);
        Logging.themsgHandlerUpdateDelegate += new Logging.msgHandlerUpdateDelegate(ConsoleUpdate);
    }
}

public class ClassOnOtherThread
{
    // In a different class running on a different thread the following line occasionly invokes the error:

    private void BootHw(string Resource, string Resource2)
    {
        Logging.Write("\t\t[");
    }
}
Run Code Online (Sandbox Code Playgroud)

我阅读MSDN建议Console.WriteLine和Console.Write是线程安全的,因此我实际上并不需要锁定它....我也无法相信它的微软的代码是错的(;-)所以我是猜测它是我的代码正在做的一些交互,它会产生错误.

现在我的问题:我应该做些什么来阻止Console.WriteLine和Console.Write被中断?...我猜这是它打断它的东西......但我真的不知道!!

任何帮助我都非常感激.

问候,

戈登.

小智 8

我有同样的问题.

console.readkey()在主线程中使用以防止在调试模式下关闭应用程序.

在我用无限循环替换它后,我的问题解决了.


Eth*_*iac 2

您应该通过删除日志记录周围的锁来解决您的问题。日志记录是通过Console.WriteLine同步(并且线程安全)完成的。您可能通过自己的锁定机制导致死锁(尽管我无法在没有看到代码的情况下进行验证)。