Async Task rather than Async void

We received the following error message when we attempt to execute the following. It does work when you add ConfigureAwait(false) but we think it’s not the right solution.

An asynchronous module or handler completed while an asynchronous operation was still pending.

public async Task Get(int id)
{

var action = await bucket.UpsertAsync(string.Format(“person::{0}”, person.Id), person);

}

While UpsertAsync is returned as a Task, this fails when the methods further down are using void.
For example (among other places):
public override async void SendAsync(byte[] request, Func<SocketAsyncState, Task> callback)

Using async void will return this error. Suggest using Task rather than void.

Can Couchbase review and provide any background on why async void was used and if/when there will be a change to move to Task.

@salmons

I’m not sure if I understand everything you were saying. However, I think the key takeaway here is that UpsertAsync causes a deadlock if you await it in the synchronization context without calling .ConfigureAwait(false)?

If my understanding is correct, could you file at a bug at http://issues.couchbase.com. If you want, you can also create a pull request that fixes it via GitHub.

Thanks,
Brant

@salmons -

It was a conscious design decision since we are not awaiting anything within that method - the callback is invoked and the await happens there. Also, while I agree favoring Task over void, there is no TaskCompletionSource or Task.FromResult which returns Task…only Task, so you end up putting a “dummy” value for the result and ignoring it. That doesn’t feel right either. That being said, I am open to suggestions and improvements here.

The error “An asynchronous module or handler completed while an asynchronous operation was still pending.” is likely a bug that is an effect of another error, such as an IO error (flakey network, whatever) when the buffer is returned by the SocketAsyncEventArgs instance. In this case the error has no impact (the operation has already failed and either will be retried until timeout or fail outright) and is just logged.

Curious, which version of .NET and which SDK version are you using?

-Jeff