代码之家  ›  专栏  ›  技术社区  ›  Dan McClain

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

  •  2
  • Dan McClain  · 技术社区  · 16 年前

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

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

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

    3 回复  |  直到 16 年前
        1
  •  2
  •   John    16 年前

    我想你应该用国旗之类的东西来代替国旗 mutex .

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

    1. 在异步完成方法中,添加“myMutex.Release();”
    2. 在main方法中,在调用异步方法后,添加“myMutex.WaitOne();”。这将阻止线程,直到异步调用完成。

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

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

    :根据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
  •  2
  •   Alexander Torstling    16 年前

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

    CountdownEvent Class

        3
  •  1
  •   Thorarin    16 年前

    这最多可以同时调用一次 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();
        }
    }
    
    推荐文章