阻止开发人员调用System.Windows.Forms.Application.DoEvents()的最佳方法是什么?

时间:2009-03-15 12:41:50

标签: c# .net vb.net

我们花了300个工时来修复现场的错误应用程序。这一切都归结为调用Application.DoEvents(re-entrancy problem)。

这没有在设计评论,代码评论中发现。两年前插入的代码是第一个版本;应用程序总是“不稳定”,但最近的变化在很大程度上暴露了重新入侵问题。

此事件是我们组织中第二次发生Application.DoEvents导致失败和多人工作时间的调试。在这种情况下,通过简单地注意到调用将其隐藏在异步任务的复杂事件处理程序中,就发现了它。

您建议如何防止此问题再次发生:

  • 为源代码管理添加签入大门?
  • 开发人员培训?
  • 代码分析规则(为什么这不是内置规则?)

如何执行编码练习?

8 个答案:

答案 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