我想知道是否要在每次迭代中将线程暂停一段定义的时间(我正在运行一个连续循环)。
我的首选是使用Task.Delay
,但我不知道是否可能有任何问题。我应该只使用Thread.Sleep
还是EventWaitHandle
吗?
class UpdateThread {
private Thread thread;
Fabric.Client client;
public UpdateThread(Fabric.Client client) {
}
public void Run() {
thread = new Thread(new ThreadStart(async()=>await UpdateAsync()));
}
public async Task UpdateAsync() {
while (true) {
await Task.Delay(Constants.REFRESH_INTERVAL);
}
}
}
上述方法的缺点是什么?
PS :此线程与Windows Forms
应用程序(线程)一起运行
答案 0 :(得分:1)
在这种情况下,您应该使用Task.Delay
,因为Thread.Sleep
将从.NET ThreadPool发送一个线程进入睡眠状态,而这很可能不是您想要的。您还将混合较低级别的Thread
和较高级别的Task
。您不需要启动新线程。只需调用UpdateAsync()
而不调用Wait()
或类似的电话就足够了。
答案 1 :(得分:1)
您传递给Thread
的构造函数(定义为public delegate void ThreadStart()
的{{3}}委托存在潜在的问题。您为其提供了async void
lambda的事实,使它成为一劳永逸的调用。也就是说,它是异步的,但不会返回Task
来观察结果或异常。
您的新线程很可能在其内部的执行流达到第一个await something
(无论是await Task.Delay
还是其他)后结束。因此,从技术上讲,您不会在此处暂停线程。 await
之后的逻辑执行将在随机线程池线程上继续,该线程池很可能与您最初创建的线程不同。
最好使用Task.Run
而不是new Thread
。前者有ThreadStart
个async Task
的lambda,您通常应该使用它而不是async void
。因此,您可以将UpdateAsync
直接传递给Task.Run
,并让an override用于异步方法。
如果由于某些原因您仍然想坚持使用new Thread
并向其传递async void
lambda,请确保观察UpdateAsync
引发的所有异常。否则,它们将被“带外”抛出到随机池线程中,有关更多详细信息,请参见上面的链接。还要注意,创建一个新线程(然后几乎立即终止它)是一个相当昂贵的运行时操作。 OTOH,在使用Task.Run
时,通常只需要从线程池中借用/返回现有线程即可,这要快得多。
也就是说,在这种特殊情况下,您最好只使用Thread.Sleep
而不是async
方法和Task.Delay
,以避免根本不必处理异步和线程切换。这是一个客户端WinForms应用程序,通常不需要(在合理范围内)扩展,即忙碌或阻塞线程的数量。
答案 2 :(得分:0)
要阻塞当前线程时,请使用Thread.Sleep
。
要在不阻塞当前线程的情况下进行逻辑延迟,请使用Task.Delay
。
我更喜欢用Thread.Sleep
处理这种情况,因为它在我脑海中的位置较低且更有效,但这只是个人原因。