【问题标题】:How can I ensure Task.Delay is more accurate?如何确保 Task.Delay 更准确?
【发布时间】:2015-06-29 22:16:49
【问题描述】:

我有一个 WPF 应用程序,它广泛使用了 awaitasync 方法。有几个地方我打电话给await Task.Delay(...); 来插入暂停。但是我遇到的麻烦是,虽然这些停顿中的许多停顿都可以稍微停顿一下,但有些地方我绝对需要停顿是准确的。所以换句话说,如果我打电话给await Task.Delay(2000);,我的应用程序中有一些地方我需要保证它只会暂停 2 秒(而不是 2.2 秒以上)。

我认为问题在于我确实有很多不同的异步方法,所以当我告诉其中一个延迟时,线程池中没有足够的线程在它应该回来的时候留下活着,这会无意中导致比预期更长的延迟。

当您的业务需要尽可能准确地延迟延迟时,线程化的 C#“最佳实践”是什么?显然,异步方法本身似乎还不够(即使它们很容易阅读)。我应该手动创建一个具有更高优先级的线程并使用 Thread.Sleep 吗?我是否增加了线程池中的线程数?我是否使用 BackgroundWorker?

【问题讨论】:

  • 首先要检查的是为什么你认为你的线程池被阻塞了......也许你正在安排阻塞工作负载在线程池中运行,在这种情况下,我建议隔离这些情况并确保它们完全异步运行。我遇到了 HttpWebRequest(ergo WebClient 和 HttpClient)的问题,因为对异步请求的 DNS 查找实际上是同步执行的,最终导致 ThreadPool 饥饿。这类问题会影响到您吗?
  • 假设您的代码不会阻止您的延迟已经“尽可能准确”:) - Windows 不是 RT OS。高优先级线程上的忙等待是合理的选择 - stackoverflow.com/questions/9891879/…
  • 这些任务是否在 UI 线程上运行?
  • 除了潜在的ThreadPool stuttering issue,您的await Task.Delay() 延续(很可能)通过DispatcherSynchronizationContext.Post 封送回WPF UI 线程。 UI 线程本身可能在其主消息循环迭代之间忙于做一些工作。您无法直接控制何时实际执行延续。
  • There are several places where I call await Task.Delay(...); to insert pauses. 为什么?对我来说听起来像是一个 XY 问题。您几乎不必在生产中使用Task.Delay;即使在我能想到的一个用例中(重试退避),它也不一定是准确的。

标签: c# wpf multithreading asynchronous async-await


【解决方案1】:

您无法真正使Task.Delay 本身更准确,因为它基于内部Threading.Timer,其分辨率高达15 ms,并且将回调调度到线程池需要时间。

如果您真的需要准确,您需要一个专用线程。您可以使用 Thread.Sleep 让它休眠 2 秒,然后在它醒来时执行您需要做的事情。

由于Thread.Sleep 会导致线程退出CPU 的上下文切换,因此更准确的选择是执行“忙等待”(例如,使用while 循环) .这将消除上下文切换回 CPU 的成本,这需要一些时间。

您应该意识到这些选项需要太多资源,您应该考虑这是否真的有必要。

【讨论】:

  • 15 毫秒的误差范围很好,但当它开始更像 200 多毫秒的误差范围时,我就会遇到问题。
  • @SoaperGEM 这可能是ThreadPool 的调度成本,正如您所建议的那样。
【解决方案2】:
 public static async void ExecuteWithDelay( this Action action, int delay )
    {
      //await Task.Delay(delay);

      Action a = () => { new System.Threading.ManualResetEventSlim(false).Wait(delay); };
      await Task.Factory.StartNew(a);
      action?.Invoke ();
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-10
    • 1970-01-01
    • 2016-06-19
    • 1970-01-01
    • 2015-03-18
    • 2021-05-26
    • 2023-03-17
    • 1970-01-01
    相关资源
    最近更新 更多