Csharp/C#教程:使用Console.Writeline()或Console.Write()时,multithreadingC#控制台应用程序中偶尔会挂起分享


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

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

作为multithreading我一直小心锁定日志记录类,所以只有一个线程可以一次记录消息…..当我发现挂起时,我得到的是线程阻塞锁和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("tt["); } } 

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

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

任何帮助我都非常感激。

问候,

戈登。

我有同样的问题。

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

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

Consol.Writeline()是线程安全的。 所以

我一直小心翼翼地锁定日志记录类

这不应该是必要的,很可能是死锁的遗留问题。 没有任何代码示例,就无法说出是/如何/什么。

所以我猜这是我的代码正在进行的一些交互,这会产生错误。

很有可能。

这是我猜它打断它的东西..

没有。

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

这是一个很长的镜头,但我想知道你是否用ToString()方法锁定的对象调用Console.WriteLine。 如果是这样,您可以让自己处于与Console.WriteLine内部锁定相关的死锁状态。

我曾经将此错误报告发布到Microsoft Connect,但遗憾的是他们拒绝修复它。

我想你的应用程序是由另一个重定向stderr和stdout的进程启动的。 如果您的“观察者”进程对同一线程上的两个流使用ReadToEnd() ,则可能会死锁。

死锁的另一个选择是通过stdin发送子进程输入,而stdin又启动另一个进程,该进程有一个无限期等待输入的控制台。 这一次发生在wmic.exe上,当stdin被重定向时会阻塞。

如果您使用过您的日志类,我怀疑您使用自己的日志类更改了底层的Console.Out。 请至少发布您的应用程序挂起的callstack,以便我们分析一些内容。 如果用自己的控制台替换控制台流,有很多方法可以用脚射击自己。

你的,Alois Kraus

上述就是C#学习教程:使用Console.Writeline()或Console.Write()时,multithreadingC#控制台应用程序中偶尔会挂起分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/953615.html

(0)
上一篇 2021年11月19日
下一篇 2021年11月19日

精彩推荐