如何在单个线程上异步执行慢速方法

本文关键字:执行 方法 异步 单个 线程 | 更新日期: 2023-09-27 18:26:20

假设我在WindowsFormsApplication中有以下基本代码。

ButtonClick(object sender, System.EventArgs e)
{
    Stopwatch SW = new Stopwatch();
    SW.Start();
    WriteToGui("Hello World");
    textBox1.Text += String.Format("Updated in {0} ms.{1}",
        SW.Elapsed.TotalMilliseconds,
        System.Environment.NewLine);
}
WriteToTheGUI(string newMessage)
{
     textBox1.Text += String.Format("{0}{1}", newMessage, System.Environment.NewLine);
}

我会得到一个文本框,看起来像这样:

Hello World
Updated in 0.5000 ms

我希望输出实际为:

Updated in 0.0005 ms
Hello World

编辑:删除了之前所有的额外信息。

文本框控件本身有一个可以使用BeginInvoke调用的消息泵。

如何将所提供调用的测试更新部分替换为将更新添加到文本框消息泵并稍后处理的调用?

编辑3:人们过于关注UI本身,而不是手头的任务,所以我将尝试解释目标。

我有一个外部的第三方数据库记录和处理一些专门的消息。

我注意到基本的发送消息命令大约需要0.5毫秒,我相信它会等待服务器的回复,即它收到了消息。潜在的消息是突发的,所以我可以很快记录数千条或更多的消息。因此,代码可能会变得非常备份。消息按时间显示如下:

[        ][        ][        ][       ][       ]  and so on and the time keeps growing with more messages.

每个括号表示从每个消息调用返回的时间。我希望它是:

[        ]
  [        ]
    [        ]   and so on so I am done with them quickly and waiting for replies.

软件和数据库可以(据说)处理我试图实现的更高的消息速率。无论哪种方式,我都会尽我所能,尽快等待。该软件要求从创建连接的线程发送任何更新,或者使用BeginInvoke正确发送消息。这就是我举UI作为例子的原因。

我不需要等待来自数据库的任何响应或错误,因为这是单独处理的,我只需要尽快发送消息并等待回复。

我可以看到两种方法来做到这一点,对于每条消息,为每条消息创建一个新的线程,这将给我留下数千个线程,或者使用具有有限线程的线程池,这将再次很慢,因为最终它将在发送更多消息之前等待。

但我不认为有任何必要创建和无限数量的线程。我应该能够使用BeginInvoke将消息添加到消息泵中,即使我不需要这样做。愚蠢的是,当我在同一个线程上时,我不知道如何做到这一点。我只需要任何函数方法的强制BeginInvoke的语法。然后我可以自由地做我喜欢的事情,并且只受消息泵处理速度的限制。

更新:

看看这里的帖子:如何从C#中的另一个线程更新GUI?将WriteToGUI中的行更改为:

 textBox1.BeginInvoke(new Action(() => textBox1.Text += String.Format("{0}{1}", newMessage, System.Environment.NewLine)));

之前的实际输出

Hello World
Updated in .2783 ms.

以及之后:

Updated in 0.0494 ms.
Hello World

这给出了立即返回并在该时间之后打印"Hello World"的期望结果。但是,示例中的Action是启动一个新线程,还是这是对新操作进行排队的最佳方法?

如何在单个线程上异步执行慢速方法

在人类的时间尺度上,半毫秒是一段非常非常短的时间。它不像是在说半秒钟或诸如此类的话。

无法从其他线程更新文本框的文本。您只能从UI线程中执行此操作。

如果你有一个长期运行的非UI操作(目前你有非常快的UI操作),那么你可以明智地考虑寻找替代方案。