首页 > 解决方案 > 通过保持线程模拟打字

问题描述

我正在编写一个带有一个组件的机器人,该组件通过通知用户“机器人正在打字......”来模拟打字。为此,必须每 10 秒通知托管该机器人的服务提供商该机器人仍在工作。

机器人“打字”的秒数简单地由字符串的长度除以“每秒字符数”的任意值来确定。

var text = "This is my response!";
var alertServiceInSeconds = 10;
var delay = text.Length / (double) charactersPerSecond;

所以必须执行两个任务:delay在调用方法 every期间让线程休眠alertServiceInSeconds

我尝试了几种方法,但机器人似乎会在delay + alertServiceInSeconds几秒钟内回复,而不仅仅是delay几秒钟。我一定在这个小学数学中遗漏了一些东西。

而 Stopwatch.Elapsed

来自:如何在特定时间执行循环

Math.Abs由于调用的次数,我觉得这种方法应该伤害我的灵魂。此外,TriggerTyping 的调用频率比alertServiceInSeconds.

var stopwatch = new Stopwatch();
stopwatch.Start();
while (stopwatch.Elapsed < TimeSpan.FromSeconds(delay))
{
    if (Math.Abs((stopwatch.ElapsedMilliseconds * 1000) / alertServiceInSeconds % 1) == 0)
        await client.TriggerTyping();
}
stopwatch.Stop();

await client.SendMessage(text);

线程.睡眠

这似乎完成了工作,但不像前面提到的那样准确。

for (var i = 0; i < delay; i++)
{
    Thread.Sleep(TimeSpan.FromSeconds(1));
    if (Math.Abs(i / alertServiceInSeconds % 1) == 0)
        await client.TriggerTyping();
}

await client.SendMessage(text);

问题:

  1. 这如何导致机器人在delay + alertServiceInSeconds几秒钟内“输入”?
  2. 这些方法的策略好吗?依赖于 TimeSpan 的 sleep for 循环和 while 循环似乎都有缺陷,但我想不出更好的方法。

标签: c#performance

解决方案


您需要 alertServiceInSeconds % 10,而不是 alertServiceInSeconds % 1。

您还可以从任务调度库和队列中受益。


推荐阅读