【发布时间】:2015-06-29 22:16:49
【问题描述】:
我有一个 WPF 应用程序,它广泛使用了 await 和 async 方法。有几个地方我打电话给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 线程上运行?
-
除了潜在的
ThreadPoolstuttering 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