简体   繁体   English

Task.Delay(Timeout.Infinite)是一个非阻塞调用,可以用来无限期地无阻塞地进行睡眠吗?

[英]Is Task.Delay(Timeout.Infinite) a non-blocking call and can be used to sleep indefinitely without blocking?

I am using Cosmos DB Change Feed library to process documents from Change Feed. 我正在使用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();

In the above code, after registering the observer factory, I need to hold this thread for an indeterminate time. 在上面的代码中,在注册观察者工厂之后,我需要保持这个线程一段不确定的时间。 Hence I use Task.Delay with infinite timeout value. 因此我使用具有无限超时值的Task.Delay。

Questions: 问题:

  1. I wanted to know if it is right to use Task.Delay() in this way. 我想知道以这种方式使用Task.Delay()是否正确。
  2. I am concerned Task.Delay() will block a thread internally in case of infinite timeout to monitor the cancellation token. 我担心Task.Delay()会在无限超时的情况下在内部阻塞一个线程来监视取消令牌。

Basically, I want a non-blocking sleep call that waits indefinitely without blocking. 基本上,我想要一个无阻塞的睡眠调用,无限期地等待而不会阻塞。

It feels a bit strange to use Task.Delay for that (especially because the cancel, which is expected, causes a CancellationException ) . 使用Task.Delay感觉有点奇怪(特别是因为取消,这是预期的,会导致CancellationException )。 I prefer to use SemaphoreSlim for Tasks like this. 我更喜欢使用SemaphoreSlim来完成这样的任务。

    private readonly SemaphoreSlim blockUntilFinishedOrCancel = new SemaphoreSlim(0);

    //Wait
    await this.blockUntilFinishedOrCancel.WaitAsync():

    //No More Waiting
    this.blockUntilFinishedOrCancel.Release(1);

This is alternative not exactly answer to the question. 这是另一种选择,而不是问题的答案。

You need to block the access to host.UnregisterObserversAsync() until some event occur right ? 您需要阻止对host.UnregisterObserversAsync()的访问,直到某些事件发生为止?

You can use Monitor to simulate something like producer / consumer scenario. 您可以使用Monitor来模拟生产者/消费者场景。

Your approach should also do the job, but it looks a bit hacky ... on the other side the producer / consumer may be an overkill for something simple. 你的方法也应该做的工作,但它看起来有点hacky ...另一方面,生产者/消费者可能是一个简单的过度杀手。 Play with the code and see what feels right for you. 玩代码,看看你觉得什么。

Thanks for all your answers and comments, I realize understood it wrong by seeing the below code on Change Feed usage on the internet. 感谢您的所有答案和评论,通过在互联网上查看以下有关Change Feed使用的代码,我意识到这是错误的。 Particularly misunderstood "Console.ReadLine" as blocking the thread and I need to do the same. 特别误解了“Console.ReadLine”阻塞线程,我需要做同样的事情。 But there is no need to block this thread to unregister it. 但是没有必要阻止此线程取消注册它。 It can be done by any other thread. 它可以由任何其他线程完成。

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();
}

As an alternative, I can make the ChangeFeedEventHost part of my class and expose a method to unregister it. 作为替代方案,我可以将ChangeFeedEventHost作为我的类的一部分,并公开一个方法来取消注册它。 On the CancelKeyPress event, I can call that unregsiter method. 在CancelKeyPress事件中,我可以调用该unregsiter方法。 This way I need not sleep/block a thread indeterminately. 这样我就不需要不确定地睡眠/阻塞线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM