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
之后的逻辑执行将在随机线程池线程上继续,该线程很可能与最初创建的线程不同

您最好只使用
任务。运行
而不是
新线程
。前者具有for
async 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,没问题,我认为这是正确的方法。只需注意异常处理/日志记录,这取决于该任务的性质。搜索'任务+开火并忘记”,这似乎是你的场景。