Существует ли универсальный способ синхронизировать асинхронный метод?

У нас есть этот общий сценарий, где у нас есть метод, который выполняет некоторое действие асинхронно и генерирует событие, когда это сделано.

Существуют времена, где мы хотим сделанный синхронно вместо этого, таким образом, у нас есть код, который выглядит подобным этому:

ManualResetEvent reset = new ManualResetEvent(false);
someobject.AsyncActionDone += (sender, args) => reset.Set();
someobject.PerformAsyncAction();
reset.WaitOne();

Существует ли способ записать вспомогательный метод сделать это? Я могу передать в Действии для выполнения, но я не уверен, как передать в чем-то, что позволяет вспомогательному методу знать, какое событие слушать, так как это не похоже, можно передать в EventHandler в качестве параметра.

Предпочтительно решение, которое не требует отражения

Кажется, существует некоторый беспорядок, это - образец того, на что похож класс someobject:

public class SomeClass
{
    private ExternalServer someServerOverTheNetwork = new ExternalServer();

    public event EventHandler AsyncActionDone;
    public Data SomeData { get; set; }
    public void PerformAsyncAction()
    {
        someServerOverTheNetwork.GetSomeData(OnDataRetrived);
    }

    public Data OnDataRetrived(Data someData)
    {
        AsyncActionDone(this, new DataEventArgs(someData));
    }
}
11
задан Davy8 12 February 2010 в 23:39
поделиться

2 ответа

Для меня я думаю, что лучший способ и самый простой способ - это создать временную таблицу, которая имеет все ваши связанные поля плюс дополнительное поле, которое является полем yeas/no.

, то вы будете использовать эту таблицу в качестве источника данных для непрерывной для. Для заполнения временной таблицы требуемыми данными используется функция onLoad.

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

Надеюсь, это поможет

-121--2688874-

При возникновении любой ошибки возникнут исключения. Единственные ошибки, о которых я могу думать, что это не сработает с параметром «пауза на исключениях», это синтаксические ошибки, которые происходят до того, как какой-либо из кодов будет выполнен, так что нет места для паузы в любом случае и ни один из кодов не будет запущен.

Очевидно, что Chrome не остановится на исключении, если он находится внутри блока try-catch. Он приостанавливается только на необдуманных исключениях. Я не знаю, путь это изменить.

Если нужно знать, в какой строке произошло исключение (тогда можно установить точку останова, если исключение воспроизводимо), объект Error , заданный блоку catch, имеет свойство stack , показывающее, где произошло исключение.

-121--574158-

Я бы рассмотрел возможность реализации асинхронного образца проектирования в объектах, выполняющих асинхронную операцию.

public object Operation(object arg)
{
    var ar = BeginOperation(arg, null, null);

    return EndOperation(ar);
}

public IAsyncResult BeginOperation(object arg, AsyncCallback asyncCallback, object state)
{
    AsyncResult asyncResult = new AsyncResult(asyncCallback, state);

    // Lauch the asynchronous operation

    return asyncResult;
}

private void LaunchOperation(AsyncResult asyncResult)
{
    // Do something asynchronously and call OnOperationFinished when finished
}

private void OnOperationFinished(AsyncResult asyncResult, object result)
{
    asyncResult.Complete(result);
}


public object EndOperation(IAsyncResult asyncResult)
{
    AsyncResult ar = (AsyncResult)asyncResult;

    return ar.EndInvoke();
}

С помощью этого образца можно выполнять несколько одновременных асинхронных операций над объектом.

Примечание: Вы можете легко найти реализацию общего класса AsyncResult в Интернете.

Правка:

При необходимости сохранения текущего проекта, если весь объект может иметь только одну асинхронную операцию, можно определить интерфейс IAsyncOperation и реализовать его во всем объекте.

public interface IAsyncOperation
{
    event EventHandler AsyncActionDone;
    void PerformAsyncAction();
}

Тогда вы могли бы иметь:

public static CallSynchronously(IAsyncOperation asyncOperation)
{
    ManualResetEvent reset = new ManualResetEvent(false);
    asyncOperation.AsyncActionDone += (sender, args) => reset.Set();
    asyncOperation.PerformAsyncAction();
    reset.WaitOne();
}

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

public void PerformAction()
{
    ManualResetEvent reset = new ManualResetEvent(false);
    this.AsyncActionDone += (sender, args) => reset.Set();
    this.PerformAsyncAction();
    reset.WaitOne();
}
4
ответ дан 3 December 2019 в 11:03
поделиться

Если я уловил ваш дрейф, вы можете просто использовать делегаты следующим образом: создайте делегата для вызова функции, позвольте ему вызвать

    public delegate string AsyncDelegate();

затем создайте такую ​​прокси-функцию:

 public static void ExecuteSync(AsyncDelegate func)
    {
        ManualResetEvent reset = new ManualResetEvent(false);
        int threadId;
        func.BeginInvoke((a)=>reset.Set(), null);
        reset.WaitOne();
    }

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

Наслаждайтесь!

3
ответ дан 3 December 2019 в 11:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: