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

时间:2010-01-21 15:38:53

标签: winforms c#-3.0 asynchronous multithreading blocking

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

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

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

我应该注意,这是为了快速证明我正在为我的利益相关者整理的概念,如果利益相关者签署了该项目,我将重写我们计划中令人讨厌的部分。但就目前而言,我需要等待阻塞调用异步方法的函数,直到异步调用完成为止

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

我认为您不想使用旗帜,而是想要使用mutex之类的东西。

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

  1. 创建互斥锁
  2. 在异步完成方法中,添加'myMutex.Release();“
  3. 在main方法中,调用异步方法后,添加“myMutex.WaitOne();”。这将阻止线程,直到您的异步调用完成。
  4. 自从我使用这些东西已经有一段时间了,但我很确定它应该如何运作。

    编辑:哎呀,我想我想的是semaphore,而不是互斥:

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

答案 2 :(得分:1)

这最多只能同时调用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();
    }
}