Search code examples
c#autoresetevent

AutoResetEvent with Return Value


I am trying to implement an AutoResetEvent that returns a value when it is signaled with its Set method. I tried to use volatile on the isCancelled local variable but that resulted with a syntax error. I don't want to introduce a class field just for this method. So is there a way that I can both set that AutoResetEvent and get the boolean flag to know whether the operation is succeeded or not? Here is my code.

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

Solution

  • Your sample looks fine to me except for one thing: You're adding the event handler after waiting for the next subscription event. From here, I infer that SubscribeAsync() should cause _client to enter a state where CancelOrderStatusReceived might get fired; but if you attach the event handler after the await then you will probably miss the event.

    Try inverting the two statements, and notwithstanding any other internal activity in _client, it should work.

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

    Also, you might find that you don't even need the AutoResetEvent if the event CancelOrderStatusReceived is only fired during the time spent awaiting SubscribeAsync for this operation.