Reputation: 1245
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;
}
Upvotes: 0
Views: 707
Reputation: 456677
I am trying to implement an AutoResetEvent that returns a value when it is signaled with its Set method.
If you're using one kind of synchronization primitive and find yourself thinking "I want it to do something else", then that's an indication that the incorrect synchronization primitive is being used.
"AutoResetEvent
with passing a value from Set
to Wait
" sounds to me like a producer/consumer queue, e.g., BlockingCollection<T>
.
However, the code you posted is interesting. It ends up using a synchronous synchronization primitive from an asynchronous method, which raises a red flag. It seems to me that the SubscribeAsync
+ CancelOrderStatusReceived
methods are a kind of Event-Based Asynchronous Pattern (EAP), and that the code would be made cleaner by converting this to Task-Based Asynchronous Pattern (TAP).
Upvotes: 1
Reputation: 6625
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.
Upvotes: 1