我们花了300个工时来修复现场的错误应用程序。这一切都归结为调用Application.DoEvents(re-entrancy problem)。
这没有在设计评论,代码评论中发现。两年前插入的代码是第一个版本;应用程序总是“不稳定”,但最近的变化在很大程度上暴露了重新入侵问题。
此事件是我们组织中第二次发生Application.DoEvents导致失败和多人工作时间的调试。在这种情况下,通过简单地注意到调用将其隐藏在异步任务的复杂事件处理程序中,就发现了它。
您建议如何防止此问题再次发生:
如何执行编码练习?
答案 0 :(得分:8)
每次集中构建应用程序时,都要在每个程序集上运行:
ildasm MyAssembly.exe /TEXT
然后搜索输出:
System.Windows.Forms.Application::DoEvents
如果找到,请将构建标记为失败,就好像它是编译错误一样。
答案 1 :(得分:4)
维护开发标准并将其添加到其中。
答案 2 :(得分:3)
以上所有。在你预期任何成功的机会之前,你需要教会人们规则。您可能还想告诉别人,为什么规则很重要。
以下工具可以防止您违反规则,这总是一个好主意。您的具体问题可能是FxCop规则或登记政策的地址。
相关问题:Do you have coding standards? If so, how are they enforced?
答案 3 :(得分:3)
更有效的方法是编写一个FxCop规则来标记此API的用法。如果FxCop作为构建过程的一部分启用,则会在尽早消除它,构建
答案 4 :(得分:1)
我建议对异步编程进行一些培训(使用BeginInvoke),并在另一个线程的后台执行耗时的任务。
答案 5 :(得分:1)
除了试图阻止使用呼叫之外还有 一种让它更容易发现这样的问题的方法 (以及其他问题):
在代码中使用大量ASSERT。
我的申请中遇到了类似的问题(MSQuant) 与DoEvents()和re-entrancy。但它很早就被抓住了 我自己测试期间的ASSERT,从未影响任何用户。
尽早ASSERTs捕获错误,我已经保存了许多, 多个小时的调试时间。此外,他们可能会发现错误 否则不被注意(例如产生不正确的结果)。
这是一种非常有效的练习(对努力比的高回报)。 我很多年前就已经了解它,并且从那时起就开始使用它。 当然,它并不能取代其他做法:声音 软件工程,单元测试,代码标准, 验收测试,代码检查。
请注意,触发ASSERT可能不一定会导致 ASSERT对话框(停止正常执行或停止 用户工作)或中止该程序。有可能 配置为将信息发送到日志记录系统(例如, 到文件),通过网络等
答案 6 :(得分:-1)
“我们只花了300个工时来修复现场的一个错误的应用程序。这一切都归结为调用Application.DoEvents(重新入侵问题)。”
首先我要说的是,我并不是主张将Application.DoEvents用于临时使用,而是将x为long = 0写入long.maxvalue循环而不使用它,并看看UI的响应程度。
如果不知道究竟发生了什么,很难说它是否真的是问题。
Private Sub foo()
stpw.Reset() : stpw.Start()
Do
Loop While stpw.ElapsedMilliseconds < 1000
stpw.Stop()
Debug.WriteLine("foo")
End Sub
Dim stpw As New Stopwatch
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Debug.WriteLine("")
Debug.WriteLine("but click")
Dim t As New Threading.Thread(AddressOf foo)
t.Start()
Do
Threading.Thread.Sleep(10)
'Application.DoEvents() 'uncomment to change the behavior
Loop While stpw.IsRunning
Debug.WriteLine("but exit")
End Sub
因此,假设我最初在没有违规声明的情况下编写它,但是用户抱怨UI没有响应。所以我然后添加DoEvents,但是当用户双击按钮时,我现在得到奇怪的结果。是问题DoEvents还是只是糟糕的设计。在这种情况下,我会投票给糟糕的设计。
答案 7 :(得分:-1)
缺少DoEvents是否会产生这个“好”的代码?
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
'simulate a long running task
For x As Long = 1 To Long.MaxValue - 1
'the absence of Application.DoEvents() is poor design IMHO
Next
End Sub