2

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

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

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

我应该注意,这是为了快速证明我试图为我的利益相关者整理的概念,如果利益相关者签署该项目,我将重写我们程序的违规部分。但是暂时我只需要等待阻塞调用异步方法的函数,直到异步调用完成

4

3 回答 3

2

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

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

于 2010-01-21T15:42:43.480 回答
2

我认为您不想使用标志,而是使用mutex之类的东西。

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

  1. 创建你的互斥锁
  2. 在您的异步完成方法中,添加 'myMutex.Release();"
  3. 在您的 main 方法中,调用异步方法后,添加“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();
    }
于 2010-01-21T15:48:08.837 回答
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();
    }
}
于 2010-01-21T16:28:46.240 回答