Рекомендация: блокировка выполнения во время ожидания асинхронного метода - PullRequest
2 голосов
/ 21 января 2010

Я пытаюсь адаптировать существующую программу (написанную внутри) для использования библиотеки, отличной от первоначальной. Я абстрагировал большую часть специфичного для библиотеки кода (кажется, это самая простая часть).

Проблема в том, что старая библиотека будет выполнять вызов с использованием метода блокировки, и наша внутренняя программа ожидает вызова метода блокировки, но новая библиотека использует асинхронный метод.

Мне было интересно, как лучше всего дождаться завершения асинхронной операции. Моей первой мыслью было иметь логический флаг с именем complete и вращаться в цикле while до завершения == true.

Я должен отметить, что это для быстрого подтверждения концепции, которую я пытаюсь составить для моей заинтересованной стороны, и если заинтересованные стороны подписывают проект, я переписываю оскорбительную часть нашей программы. Но на данный момент мне нужно просто подождать, пока функция не вызовет асинхронный метод, пока асинхронный вызов не завершится

Ответы [ 3 ]

2 голосов
/ 21 января 2010

Вместо флага, я думаю, вы захотите использовать что-то вроде mutex .

Для этого в этой библиотеке должно быть событие, уведомляющее вас о завершении асинхронного вызова. Это будет выглядеть так:

  1. Создайте свой мьютекс
  2. В вашем методе асинхронного завершения добавьте 'myMutex.Release (); "
  3. В вашем основном методе после вызова асинхронного метода добавьте "myMutex.WaitOne ();". Это заблокирует поток, пока ваш асинхронный вызов не будет завершен.

Прошло много времени с тех пор, как я использовал этот материал, но я уверен, что так оно и должно быть.

edit : Упс, думаю, я думал о семафоре , а не мьютексе:

    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 : предложение Пер Торарина; похоже, этот класс был разработан для обработки подобных ситуаций в .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 голосов
/ 21 января 2010

Передайте защелку обратного отсчета асинхронному методу и дождитесь защелки. Когда асинхронный метод завершится, он уведомит вас о защелке обратного отсчета, и выполнение может продолжиться. В принципе также можно использовать монитор, но он небезопасен в неудачном случае, когда асинхронный метод завершается до того, как вы сможете вызвать wait, и поэтому вы пропустите уведомление.

Да, и в мире .NET защелка обратного отсчета называется CountdownEvent: CountdownEvent Class

1 голос
/ 21 января 2010

Это должно работать не более одного одновременного вызова на 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();
    }
}
...