-1

我如何删除这个问题?我最初认为该问题与 DoEvents 有关,但事实证明并非如此。我在这里重新发布了这个问题:http: //goo.gl/VpAEK对问题进行了更恰当的描述。

谢谢-我感谢有关如何处理此问题的任何指导...


首先,我知道这个问题,因为之前已经问过一个一般概念 - 我(希望)有一个具体的变化要问。我还将开始说,我理解使用 Application.DoEvents() 的具体原因,并预先向每个人保证我们尽可能避免使用它,并且在整个过程中都有多个线程解决问题(没有 Application.DoEvents() 参与)我们的应用程序。

话虽如此,它框架的一部分——我认为在某些特定情况下它占有一席之地。

我要问的具体情况是单线程情况,纯粹涉及 UI,其中(据我了解),根据定义 - 这不能在后台线程中完成。更具体地说,我们正在加载/配置表单中的许多 UI 元素,有时需要 1-2 秒才能完成,我希望在此过程中更新一个标签,指示正在发生的事情。在后台线程中确实没有任何繁重的工作/工作要做 - 这都是 UI。

如果在 4 个标签文本更改后我没有 Application.DoEvents() 调用,则标签不会自行重绘。如果有人可以提出一个替代方案,在纯 UI、单线程环境中以不同的方式解决这个问题——我全都听好了。

问题是,偶尔,如果我仍在尝试确定,Application.DoEvents() 根本不会返回。

我真的理解所有关于 DoEvents() 方法的抱怨(其中大部分是完全有效的!!!)以及它可能导致的各种问题!因此,理想情况下,无需就 DoEvents 调用的利弊进行激烈辩论(正如几乎所有其他关于该主题的线程似乎都在做的那样)——我要回答的具体问题是——任何人都可以想到任何理由为什么 DoEvents 会简单地挂起?(即不返回)?

如果你想辩论 DoEvents() 调用本身,这里有一个很好的描述它的优点和缺点:http: //goo.gl/4BtZf

  • 我们的用户报告说,这似乎在他们使用该应用程序时不会发生,而是仅在他们离开计算机一段时间后才会发生(可能涉及屏幕保护程序?)我们在更改屏幕分辨率时注意到了它,而远程查看我们客户的计算机。
  • 我们有用户坚持认为应用程序最小化时会发生更多。
  • 我们有用户坚持认为,当应用程序被最小化时,这种情况发生得更多,他们在 IE 和/或 Outlook 中做了一些工作。

在内部,我们几乎完全无法重现它,除了今天早上我完成了上述所有操作,包括禁用我的网络连接一两分钟和 VPN 连接到服务器几分钟——所有这些都是在我们的应用程序被最小化的情况下进行的。

在此之后(实际上是我们第一次能够在内部重现它),应用程序挂起,当我附加到该进程时,它挂在 Application.DoEvents() 行上。2线法:

label.Text = "Foo"; 应用程序.DoEvents();

多个附加测试(尝试执行相同的操作)无法重现该问题。

有什么建议么?谢谢。


编辑:尝试得到一个专门关于 DoEvents 的问题的答案是禁忌吗?我对 StackOverflow 比较陌生,我只是有点困惑为什么我已经得到了两次反对票。

我已经在其他线程中多次看到这个问题,并且(至少在我看来,几乎普遍的反应是 - 不要使用 application.DoEvents())。我特别试图在我最初的问题中考虑周到,并解释为什么我们在这种情况下使用它。同时,我特别试图避免再次讨论为什么不应该使用 DoEvents。如果有足够多的人认为某事是个坏主意,那么在 stackoverflow 上讨论它只是禁忌吗?同样,我对这个论坛比较陌生,并试图了解这里的礼仪。谢谢。

4

1 回答 1

2

假设利用其他 [后台] 线程来执行此任务是错误的,这是不正确的。如果你想走那条路Application.DoEvents就好了。我不会坐在这里告诉你不能使用它,但你至少应该考虑不将其用作可能的替代方案。正如您所说,您正在做的是更新大量不同的 UI 元素。您不是在执行单个 UI 任务,而是在执行很多(数十个、数百个、数千个等等)任务。您还有一个单独的任务负责管理所有这些较小的任务。这种对较小任务的管理可以在 UI 线程或非 UI 线程中完成。如果您在 UI 线程中执行此操作,则 UI 将被阻塞,直到每个子 UI 操作完成。如果您有一个仅充当“调度程序”的非 UI 线程,则添加一些较小的 UI 任务来完成,那么这些较小的 UI 任务可以独立执行,并允许 UI 执行......无论......在一些那些任务。

这是一个例子:

private void button1_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew(() =>
    {
        for (int i = 0; i < 10; i++)
        {
            Invoke(new MethodInvoker(() => updateLabel(i)));
            Invoke(new MethodInvoker(() => longerUITask(i)));
        }
    });
}

private void longerUITask(int i)
{
    //do databinding that will take a second or two
    Thread.Sleep(1000);
}

private void updateLabel(int i)
{
    label1.Text = i.ToString();
}

这样做效率会降低吗。是的,会的。您将产生其他线程/任务,管理它们等。但是,您获得的成本是简单而有效的保证 UI 将保持响应。

于 2012-07-20T17:44:02.467 回答