我正在尝试使用以下C#语句崩溃LINQPad4:
new Thread(() => new Thread(() => { throw new Exception(); }).Start()).Start();
出现未处理异常对话框,但进程不会停止。我猜想像所有UnhandledThreadExceptions一样,IsTerminating = true...它是如何防止进程死亡的?
我正在尝试使用以下C#语句崩溃LINQPad4:
new Thread(() => new Thread(() => { throw new Exception(); }).Start()).Start();
出现未处理异常对话框,但进程不会停止。我猜想像所有UnhandledThreadExceptions一样,IsTerminating = true...它是如何防止进程死亡的?
它还有一个全局异常处理程序,用于所有非UI线程异常,类似于Main方法中的以下内容:
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
using System;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
new Thread(() => new Thread(() => { throw new ApplicationException("Ciao"); }).Start()).Start();
try
{
Application.Run(new Form1());
}
catch (Exception exc)
{
System.Diagnostics.Debug.WriteLine(exc.Message);
}
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// here catching Unhandled Exceptions
System.Diagnostics.Debug.WriteLine(e.ExceptionObject.ToString());
}
}
}
LINQPad似乎不仅执行其查询,而且还在其自己的AppDomain中加载其依赖项。如果您在应用程序中创建一个新的AppDomain,则可以友好地处理异常并以友好的方式重新加载/编译应用程序。
更有趣的是LINQPad如何处理其依赖项。显然,它们在加载到这些AppDomains时会被“影子复制”,因为我有一个自定义库,我能够“即时”对其进行更改,而LINQPad不会锁定该文件;相反,它似乎有一个FileSystemWatcher来查找文件的更改,卸载AppDomain,然后使用新的依赖项重新加载AppDomain。
在构建新库后应用程序中的“暂停”,然后通过智能感知使这些新添加的“方法”现在可用于脚本,表明LINQPad在处理可能导致崩溃的脚本和引用库时相当智能。
然而,如果你真的想玩一些有趣的东西,你总是可以使用System.Diagnostics.Debugger.Break()。如果你在LINQPad属性中关闭脚本的优化,你实际上可以调试到LINQPad进程中,将源代码放在Visual Studio调试器窗口中,设置断点,逐步执行,检查变量等,以便实际上“调试”在LINQPad中创建的代码片段。这是你脚本中的几行额外代码,但如果你在LINQPad中进行了一些重度脚本/测试,那么它绝对是值得的。
这仍然是我能找到的最好的工具之一,用于原型设计、单元测试和构建使用LINQ查询的C#代码,我可以轻松地将它们剪切并粘贴到应用程序中,并相对容易地确保它们的行为与观察到的一致。