我正在寻找.NET中的一种方法(特别是2.0,C#),以便触发调试中断,就像在该点设置断点一样,而不必记住在调试器中设置特定的断点,并且不干扰生产运行时.
我们的代码需要在生产中吞下异常,所以我们不会破坏链接到我们的客户端应用程序,但是我正在尝试将其设置为如果它恰好在调试器中运行时会弹出这样的错误进行分析,否则将被安全地忽略.
我的使用尝试Debug.Assert(false)不太理想,我认为这样做Debug.Fail()会有相同的表现.理论上它应该在生产中没有效果,并且在调试时它确实成功停止,但是根据设计(如我所知)如果你想忽略该错误就没有办法继续执行,就像你可以使用实际的断点一样,就像我们吞下错误的生产一样.它显然也打破了变量状态的评估,因为调试器实际上在本机系统代码中停止而不是在我们的代码中,所以它的调试帮助是有限的.(也许我错过了某些方法来重新审视变量等等.它发生的地方.???)
我希望有类似的东西Debug.Break(),但它似乎不存在(除非可能在.NET的更高版本中?),也没有其他Debug方法似乎适用.
更新:虽然ctacke的答案是我所寻找的最佳匹配,但我还发现了Debug.Assert()的一个技巧 - 在调试器中运行时 - 暂停调试器,转到Debug的代码.断言呼叫挂起(以绿色突出显示,因为它在框架代码中已关闭)并按下Step-Out(shift-F11),然后在断言对话框中点击Ignore.这将使调试器在断言返回时暂停(并且能够继续执行,就像它没有发生一样,因为它被忽略了).可能有其他方法可以做同样的事情(点击重试更直接吗?),但这种方式很直观.
编辑for intro:
我们知道C#中的ref参数传递对变量的引用,允许在被调用的方法中更改外部变量本身.但是引用的处理方式与C指针非常相似(每次访问该参数时都会读取原始变量的当前内容,并且每次修改参数时都会更改原始变量),或者被调用的方法可以依赖于一致的引用.通话时间?前者提出了一些线程安全问题.特别是:
我在C#中编写了一个静态方法,它通过引用传递一个对象:
public static void Register(ref Definition newDefinition) { ... }
Run Code Online (Sandbox Code Playgroud)
调用者提供一个已完成但尚未注册的Definition对象,经过一些一致性检查后,我们"注册"他们提供的定义.但是,如果已经存在具有相同密钥的定义,则它不能注册新密钥,而是将其引用更新Definition为该密钥的"官方" .
我们希望这是严格的线程安全,但我想到了一个病态场景.假设客户端(使用我们的库)以非线程安全的方式共享引用,例如使用静态成员而不是局部变量:
private static Definition riskyReference = null;
Run Code Online (Sandbox Code Playgroud)
如果一个线程设置riskyReference = new Definition("key 1");,填写定义,并调用我们Definition.Register(ref riskyReference);而另一个线程也决定设置riskyReference = new Definition("key 2");,我们保证在我们的Register方法中newDefinition我们正在处理的引用不会被其他线程修改我们(因为引用了对象被复制并将在我们返回时复制出来?),或者其他线程可以在执行过程中替换我们上的对象(如果我们引用指向原始存储位置的指针???)打破我们的理智检查?
请注意,这与对基础对象本身的更改不同,这对于引用类型(类)当然是可能的,但可以通过该类中的适当锁定来轻松防范.但是,我们不能保护对外部客户端变量空间本身的更改!我们必须在方法的顶部创建我们自己的参数副本并覆盖底部的参数(例如),但这对于编译器来说似乎更有意义,因为处理的是精神错乱.不安全的参考.
因此,我倾向于认为引用可以被编译器复制并复制出来,以便该方法处理对原始对象的一致引用(直到它在需要时更改自己的引用),而不管是什么发生在其他线程上的原始位置.但是我们在文档和参考参数的讨论中找不到关于这一点的确定答案.
有人可以通过明确的引用来缓解我的担忧吗?
编辑得出结论:
用多线程代码示例确认了它(感谢Marc!)并进一步思考它,它确实是我自己所担心的非自动线程安全行为."ref"的一点是通过引用传递大结构而不是复制它们.另一个原因是你可能想要设置一个变量的长期监控,并且需要传递对它的引用,这将看到变量的变化(例如,在null和活动对象之间切换),这是一个自动复制 - in/copy-out不允许.
因此,为了使我们的Register方法能够抵御客户端的疯狂,我们可以像下面这样实现它:
public static void Register(ref Definition newDefinition) {
Definition theDefinition = newDefinition; // Copy in.
//... Sanity checks, actual work...
//...possibly …Run Code Online (Sandbox Code Playgroud) 当应用程序退出时,需要通知我们的代码库.所以我们订阅了System.Window.Forms.Application.ApplicationExit事件.这适用于Winforms应用程序,但它是否也适用于其他类型的应用程序,如控制台应用程序,服务和Web应用程序(如ASP.NET)?命名空间会表明它没有,并且可能在Application.Exit()被调用时(明确地或隐含地)被提升,这可能不适合调用这些其他情况.
还有一些其他事件在这些其他情况下会更好,或者更普遍吗(如果它适用于Winforms也很好)?例如,是否有一个关于何时Environment.Exit()被调用的事件(控制台应用程序)?
我在System.Diagnostic.Process中发现了一个Exited事件,但这似乎是为了监视另一个进程的退出,并且它似乎没有被进程接收到它自己(例如,Process.GetCurrentProcess().Exited += Process_Exited; Process.GetCurrentProcess().EnableRaisingEvents = true;).我认为它可能只是在该过程实际退出后才会提出,所以这不起作用.
这尤其适用于.NET 2.0和C#.