最佳实践:在等待异步方法时阻止执行

发布于 2024-08-18 07:21:06 字数 307 浏览 8 评论 0原文

我正在尝试调整现有程序(内部编写的)以使用与最初不同的库。我已经抽象了大部分特定于库的代码(似乎是更容易的部分)。

问题是,旧库将使用阻塞方法执行调用,而我们的内部程序期望调用阻塞方法,但新库使用异步方法。

我想知道等待异步操作完成的最佳实践是什么。我的第一个想法是有一个名为completed的布尔标志,并在一个while循环中旋转,直到completed==true。

我应该指出,这是为了快速证明我试图为我的利益相关者组合在一起的概念,如果利益相关者签署了该项目,我将重写我们程序中的违规部分。但目前,我需要等待调用异步方法的函数直到异步调用完成

I am trying to adapt an existing program (internally written) to use a different library than it originally did. I've abstracted most of library-specific code away (seems to be the easier part).

The issue is, the old library would execute a call using a blocking method, and our internal program is expecting a blocking method to be called, but the new library uses an async method.

I was wondering what the best practice would be for waiting for the async operation to complete. My first thought was to have a boolean flag called completed, and spin in a while loop until completed == true.

I should note that this is for a quick proof of concept I'm trying to put together for my stakeholder, and if the stakeholders sign off on the project, I'm going to rewrite the offending part of our program. But for the time being, I need to just wait for the block the function calling the async method until the async call is complete

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

晨曦慕雪 2024-08-25 07:21:06

我认为您不想使用标志,而是使用 互斥体

为了做到这一点,该库需要有一个事件来在异步调用完成后通知您。它看起来像这样:

  1. 创建互斥体
  2. 在异步完成方法中,添加“myMutex.Release();”
  3. 在主方法中,调用异步方法后,添加“myMutex.WaitOne();”。这将阻塞线程直到你的异步调用完成。

我已经有一段时间没有使用这个东西了,但我很确定它应该是这样工作的:

哎呀,我想我在想。 信号量,而不是互斥体:

    private static Semaphore mySemaphore = new Semaphore(0, 1);

    static void Main(string[] args)
    {
        Console.WriteLine("Waiting on async call");
        (new Thread(ASyncCallCompleted)).Start();
        mySemaphore.WaitOne();
        Console.WriteLine("Waiting Completed");
    }

    private static void ASyncCallCompleted()
    {
        Thread.Sleep(5000);
        mySemaphore.Release();
    }

编辑 #2:根据 Thorarin 的建议;听起来这个类是为了处理 .Net 中的这种情况而设计的:

    private static AutoResetEvent mySync = new AutoResetEvent(false);

    static void Main(string[] args)
    {
        Console.WriteLine("Waiting on async call");
        (new Thread(ASyncCallCompleted)).Start();
        mySync.WaitOne();
        Console.WriteLine("Waiting Completed");
        Console.Read();
    }

    private static void ASyncCallCompleted()
    {
        Thread.Sleep(5000);
        mySync.Set();
    }

Instead of a flag, I'd think you'd want to use something like a mutex.

In order to do this, that library needs to have an event to notify you once your async call is done. It would look like this:

  1. Create your mutex
  2. In your async complete method, add in 'myMutex.Release();"
  3. In your main method, after you call the async method, add in "myMutex.WaitOne();". This will block the thread until your async call is complete.

It's been a while since I've used this stuff, but I'm pretty sure that's how it should work.

edit: Oops, I think I was thinking of a semaphore, not mutex:

    private static Semaphore mySemaphore = new Semaphore(0, 1);

    static void Main(string[] args)
    {
        Console.WriteLine("Waiting on async call");
        (new Thread(ASyncCallCompleted)).Start();
        mySemaphore.WaitOne();
        Console.WriteLine("Waiting Completed");
    }

    private static void ASyncCallCompleted()
    {
        Thread.Sleep(5000);
        mySemaphore.Release();
    }

edit #2: Per Thorarin's suggestion; it sounds like this class was designed to handle situations like this in .Net:

    private static AutoResetEvent mySync = new AutoResetEvent(false);

    static void Main(string[] args)
    {
        Console.WriteLine("Waiting on async call");
        (new Thread(ASyncCallCompleted)).Start();
        mySync.WaitOne();
        Console.WriteLine("Waiting Completed");
        Console.Read();
    }

    private static void ASyncCallCompleted()
    {
        Thread.Sleep(5000);
        mySync.Set();
    }
各空 2024-08-25 07:21:06

将倒计时锁存器传递给异步方法,并等待锁存器。当异步方法完成时,它将通知您倒计时锁存器,并且可以继续执行。原则上也可以使用监视器,但在不幸的情况下是不安全的,即异步方法在您可以调用 wait 之前完成,因此您会错过通知。

哦,在 .NET 世界中,倒计时锁存器称为 CountdownEvent: CountdownEvent 类

Pass a countdown latch to the async method, and wait on the latch. When the async method is complete, it will notify you on the countdown latch, and execution can continue. A monitor could in principal also be used, but is unsafe in the unfortunate case that the async method completes before you can call wait, and you therefore miss the notify.

Oh, and in the .NET world, a countdown latch is called a CountdownEvent: CountdownEvent Class

趁微风不噪 2024-08-25 07:21:06

这应该适用于最多一次同时调用 BlockingCall。否则,您将需要单独的 AutoResetEvent 实例来确定哪个调用已完成。反正:

delegate void Callback();

class BlockAsync
{
    AutoResetEvent _waitHandle = new AutoResetEvent(false);

    public void BlockingCall()
    {
        AsyncCall(AsyncCallCompleted);
        _waitHandle.WaitOne();
    }

    void AsyncCall(Callback callback)
    {
        // Example is not actually asynchronous, to demonstrate the solution
        // is free of race conditions.
        callback();
    }

    void AsyncCallCompleted()
    {
        _waitHandle.Set();
    }
}

This should work for at most one simultaneous call to BlockingCall. Otherwise you will need separate AutoResetEvent instances to determine which call has finished. Anyway:

delegate void Callback();

class BlockAsync
{
    AutoResetEvent _waitHandle = new AutoResetEvent(false);

    public void BlockingCall()
    {
        AsyncCall(AsyncCallCompleted);
        _waitHandle.WaitOne();
    }

    void AsyncCall(Callback callback)
    {
        // Example is not actually asynchronous, to demonstrate the solution
        // is free of race conditions.
        callback();
    }

    void AsyncCallCompleted()
    {
        _waitHandle.Set();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文