AutoResetEvent с возвращаемым значением - PullRequest
0 голосов
/ 01 августа 2020

Я пытаюсь реализовать AutoResetEvent, который возвращает значение, когда о нем сигнализирует его метод Set. Я попытался использовать volatile для локальной переменной isCancelled, но это привело к синтаксической ошибке. Я не хочу вводить поле класса только для этого метода. Итак, есть ли способ, которым я могу установить это AutoResetEvent и получить логический флаг, чтобы узнать, успешно ли выполнена операция? Вот мой код.

private async Task<bool> GetCancelOrderStatus(Pair pair)
{
    var autoResetEvent = new AutoResetEvent(false);
    var isCancelled = false;

    var options = new SubscribeOptions(SubscribeOptionNames.CancelOrderStatus);
    var subscribe = new Subscribe(new[] { pair }, options);

    await _client.SubscribeAsync(subscribe);

    _client.CancelOrderStatusReceived += (sender, args) =>
    {
        if (args.Message.Status == Status.Ok)
            isCancelled = true;

        autoResetEvent.Set();
    };

    autoResetEvent.WaitOne();

    return isCancelled;
}

Ответы [ 2 ]

1 голос
/ 02 августа 2020

Я пытаюсь реализовать AutoResetEvent, который возвращает значение, когда оно передается с помощью его метода Set.

Если вы используете один вид примитива синхронизации и обнаруживаете, что думаете " Я хочу, чтобы он сделал что-то еще ", тогда это признак того, что используется неправильный примитив синхронизации.

« AutoResetEvent с передачей значения от Set до Wait »звучит для меня как очередь производителя / потребителя, например, BlockingCollection<T>.

Однако опубликованный вами код интересен. В конечном итоге он использует примитив синхронной синхронизации из асинхронного метода, что поднимает красный флаг. Мне кажется, что методы SubscribeAsync + CancelOrderStatusReceived являются своего рода асинхронным шаблоном, основанным на событиях (EAP), и что код будет чище, преобразовав его в асинхронный шаблон, основанный на задачах (TAP). .

1 голос
/ 02 августа 2020

Ваш образец мне нравится, за исключением одного: вы добавляете обработчик событий после ожидания следующего события подписки. Отсюда я делаю вывод, что SubscribeAsync() должен привести _client к переходу в состояние, при котором CancelOrderStatusReceived может быть запущен; но если вы присоедините обработчик событий после ожидания, вы, вероятно, пропустите событие.

Попробуйте инвертировать два оператора, и, несмотря на любые другие внутренние действия в _client, он должен работать.

private async Task<bool> GetCancelOrderStatus(Pair pair)
{
    var autoResetEvent = new AutoResetEvent(false);
    var isCancelled = false;

    var options = new SubscribeOptions(SubscribeOptionNames.CancelOrderStatus);
    var subscribe = new Subscribe(new[] { pair }, options);

    _client.CancelOrderStatusReceived += (sender, args) =>
    {
        if (args.Message.Status == Status.Ok)
            isCancelled = true;

        autoResetEvent.Set();
    };

    await _client.SubscribeAsync(subscribe);

    autoResetEvent.WaitOne();

    return isCancelled;
}

Кроме того, вы можете обнаружить, что вам даже не нужен AutoResetEvent, если событие CancelOrderStatusReceived запускается только во время ожидания SubscribeAsync для этой операции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...