C# Task.Delay(Timeout.Infinite)是一个非阻塞调用,可以用于无限期睡眠而不阻塞吗?

C# Task.Delay(Timeout.Infinite)是一个非阻塞调用,可以用于无限期睡眠而不阻塞吗?,c#,task,C#,Task,我正在使用Cosmos DB Change Feed库来处理来自Change Feed的文档 var docObserverFactory = DocumentFeedObserverFactory.Create(myCollectionInfo); await host.RegisterObserverFactoryAsync(docObserverFactory); Console.WriteLine("Awaiting indefinitely...press Cancel to exit

我正在使用Cosmos DB Change Feed库来处理来自Change Feed的文档

var docObserverFactory = DocumentFeedObserverFactory.Create(myCollectionInfo);
await host.RegisterObserverFactoryAsync(docObserverFactory);
Console.WriteLine("Awaiting indefinitely...press Cancel to exit");

// I set the CancellationToken to true on Console.CancelKeyPress Event
await Task.Delay(Timeout.Infinite, cancellationToken);
await host.UnregisterObserversAsync();
在上面的代码中,在注册了observer工厂之后,我需要在一段不确定的时间内保持该线程。因此,我使用具有无限超时值的Task.Delay

问题:

  • 我想知道这样使用Task.Delay()是否正确
  • 我担心Task.Delay()会在无限超时的情况下在内部阻止线程以监视取消令牌

  • 基本上,我想要一个无阻塞的睡眠呼叫,它可以无限期地等待而不阻塞。

    这不是问题的确切答案

    您需要阻止对主机的访问。
    host.UnregisterObserversAsync()
    ,直到某个事件发生,对吗

    您可以使用来模拟类似场景的内容


    你的方法应该也能做到,但它看起来有点粗糙。。。另一方面,生产商/消费者可能对简单的事情过于苛刻。玩一下代码,看看什么对你来说合适。

    使用Task感觉有点奇怪。为此延迟(特别是因为预期的cancel会导致
    CancellationException
    )。对于这样的任务,我更喜欢使用
    信号量lim

        private readonly SemaphoreSlim blockUntilFinishedOrCancel = new SemaphoreSlim(0);
    
        //Wait
        await this.blockUntilFinishedOrCancel.WaitAsync():
    
        //No More Waiting
        this.blockUntilFinishedOrCancel.Release(1);
    

    谢谢你的回答和评论,我意识到在互联网上看到下面关于更改提要用法的代码是错误的。特别是将“Console.ReadLine”误解为阻塞线程,我也需要这样做。但是没有必要阻止这个线程来注销它。它可以由任何其他线程完成

    using (DocumentClient destClient = new DocumentClient(destCollInfo.Uri, destCollInfo.MasterKey))
    {
        DocumentFeedObserverFactory docObserverFactory = new DocumentFeedObserverFactory(destClient, destCollInfo);
    
        ChangeFeedEventHost host = new ChangeFeedEventHost(hostName, documentCollectionLocation, leaseCollectionLocation, feedOptions, feedHostOptions);
        await host.RegisterObserverFactoryAsync(docObserverFactory);
    
        // This is where I thought I need to block this thread indeterminately.
        Console.WriteLine("Running... Press enter to stop.");
        Console.ReadLine();
    
        await host.UnregisterObserversAsync();
    }
    

    作为替代方案,我可以使ChangeFeedEventHost成为类的一部分,并公开一个方法来注销它。在CancelKeyPress事件中,我可以调用unregister方法。这样,我就不需要不确定地睡眠/阻塞线程。

    Task.Delay()
    保持任务打开,但不阻止任何其他操作,如果这是你的意思,这与
    thread.sleep()
    不同。我读了一篇关于这一点的文章:你所说的“我需要保持这个线程”到底是什么意思。什么是“抓住”一根线?这没有错。没有线程,除了让所有计时器都在滴答滴答地运行的线程外,您只需为计时器对象付费。为什么不能直接注销而不是发送取消令牌的信号,这一点并不十分明显。我想是因为需要使用async来注销,所以我被卷入了这段代码中。顺便说一句,做些有用的事情。顺便说一下,取消令牌并不是要取消正在运行的任务,它更多的是取消计划任务。这是一种误导性的概念。