microsoft / MixedReality-WebRTC

MixedReality-WebRTC is a collection of components to help mixed reality app developers integrate audio and video real-time communication into their application and improve their collaborative experience
https://microsoft.github.io/MixedReality-WebRTC/
MIT License
913 stars 283 forks source link

Use TaskCompletionSource to avoid blocking threads in C# library #198

Open djee-ms opened 4 years ago

djee-ms commented 4 years ago

Currently some C# async calls like SetRemoteDescriptionAsync() (see #195) are spawing a background Task and inside it waiting on an event to wait from a completion signal from the C interop layer. This This wait is often achieved with ManualResetEventSlim, which blocks the thread executing the task.

Instead, we should leverage TaskCompletionSource, which acts as a promise for the result of the task, and avoids blocking any thread while waiting for the low-level work completion. https://stackoverflow.com/questions/15316613/when-should-taskcompletionsourcet-be-used https://stackoverflow.com/questions/38996593/promise-equivalent-in-c-sharp

Note the caveat that this can create deadlocks, and the use of TaskContinuationOptions to work around those cases:

TaskCompletionSource type has a very peculiar behavior: by default, when SetResult method is called then all the task’s “async” continuations are invoked … synchronously.

https://devblogs.microsoft.com/premier-developer/the-danger-of-taskcompletionsourcet-class/

sipsorcery commented 4 years ago

TaskCompletionSource type has a very peculiar behavior: by default, when SetResult method is called then all the task’s “async” continuations are invoked … synchronously.

+1.

I've been burnt by this in the past in my own library. The approach below has fixed the deadlocks I discovered.

TaskCompletionSource<bool> transferAccepted = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);