C# 安全地暂停线程
我想知道如果我想在每次迭代中将一个线程暂停一段定义的时间(我正在运行一个连续的循环),是否有任何问题。 我的第一个选择是使用C# 安全地暂停线程,c#,multithreading,task-parallel-library,C#,Multithreading,Task Parallel Library,我想知道如果我想在每次迭代中将一个线程暂停一段定义的时间(我正在运行一个连续的循环),是否有任何问题。 我的第一个选择是使用Task.Delay,但我不知道是否会有任何问题。我应该选择Thread.Sleep还是EventWaitHandle class UpdateThread { private Thread thread; Fabric.Client client; public UpdateThread(Fabric.Client cl
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);
}
}
}
上述方法的缺点是什么
p.S:此线程与
Windows窗体
应用程序(线程)一起运行。在这种情况下,您应该使用Task.Delay
,因为thread.Sleep
会将.NET线程池中的线程发送到睡眠状态,而这很可能不是您想要的。您还将较低级别的线程
与较高级别的任务
混合使用。你不需要开始一个新的线程。只要调用UpdateAsync()
,而不调用Wait()
或类似的函数就足够了。要阻止当前线程时,请使用Thread.Sleep
如果需要逻辑延迟而不阻塞当前线程,请使用Task.Delay
我更喜欢用
线程来处理这种情况。睡眠
因为它在我的头脑中是较低级别和更有效的,但这只是个人的事情。传递给线程
的构造函数的委托存在潜在问题,该构造函数被定义为公共委托void ThreadStart()
。您为它提供了一个async void
lambda,这使得它成为一个fire-and-forget调用。也就是说,它是异步的,但不会返回任务
,以观察结果或异常
您的新线程很可能会在其内部的执行流到达第一个wait something
时结束,无论是wait Task.Delay
还是其他任何内容。因此,从技术上讲,这里没有暂停线程。在该wait
之后的逻辑执行将在随机线程池线程上继续,该线程很可能与最初创建的线程不同
您最好只使用任务。运行
而不是新线程
。前者具有forasync Task
lambdas,您通常应该使用它来代替async void
。因此,您可以将您的UpdateAsync
直接传递给任务。运行,并使用for async方法
如果出于某种原因,您仍然希望使用新线程
并向其传递异步void
lambda,请确保遵守UpdateAsync
引发的所有异常。否则,它们将在随机池线程上“带外”抛出,有关更多详细信息,请参阅上面的链接。还要注意,创建一个新线程(然后几乎立即结束它)是一个相当昂贵的运行时操作。另外,在使用Task.Run
时,您通常只需从线程池借用/返回一个现有线程,这要快得多
这就是说,在这种特殊情况下,您最好使用Thread.Sleep
而不是async
方法和Task.Delay
,以避免处理异步和线程切换。这是一个客户端WinForms应用程序,您通常不关心(在一定程度上)扩展,即忙线程或阻塞线程的数量。我在这里会小心,线程。睡眠通常表示您正在等待其他事情完成,除非其他事情是确定的(在点网中可能不是)这可能会引入bug。或者你可能会暂停你的线程超过必要的时间(以避免在必要的时间之前唤醒它。看看这个我倾向于任务。延迟。它有什么问题吗?我只想在定义的时间段内暂停以下代码的执行。“Thread.Sleep会将一个线程从dot net threadpool发送到Sleep”。将当前线程发送到Sleep不是Sleep的工作吗(不管它是threadpool线程).Thread.Sleep
将当前线程设置为Sleep,但是可能会在.NET线程池中的线程上调度异步方法,在这种情况下,它将被设置为Sleep。因此,基本上执行updateSync的线程在这两种情况下都将处于睡眠状态?是的,但是Thread.Sleep
不会通知TaskScheduler,因此它认为线程仍在忙于执行您的方法。我不在乎它是任务
还是线程
,只要它与主线程
解耦。它的执行是由不同的线程完成的(线程池
)只要在执行过程中每次迭代都有一个逻辑暂停,我就不会感到烦恼。这个任务/线程将充当后台工作程序,并且将具有应用程序的范围。@BercoviciAdrian,那么为什么要启动线程?您可以执行类似等待任务。延迟(刷新间隔)。配置等待(false)的操作
作为UpdateAsync
@bercoviciarian的第一句话,是的,您可以而且已经这样做了,在UpdateAsync
中。您只需将异步方法卸载到另一个线程(通常使用任务。运行)如果异步方法中有CPU密集型代码或阻塞代码。通常,只有在UI线程上调用类似的异步方法时才会引起关注。@Bercoviciarian,没问题,我认为这是正确的方法。只需注意异常处理/日志记录,这取决于该任务的性质。搜索'任务+开火并忘记”,这似乎是你的场景。