timcassell / ProtoPromise

Robust and efficient library for management of asynchronous operations in C#/.Net.
MIT License
136 stars 13 forks source link

Add Promise groups #396

Closed timcassell closed 1 month ago

timcassell commented 4 months ago

A common problem with Promise.Race is that when the first promise has completed, the rest of the operations are orphaned and left running even though their results no longer matter. The solution is to pass a cancelation token to each operation and cancel that token when the race is complete, but it's verbose and cumbersome to do that. The same problem applies to Promise.All/Merge when any of the operations are rejected or canceled (though it's not as common of an issue as race).

A more convenient way of handling this is with something known as "structured concurrency", which is essentially a method of adding operations to a group as they are created, and the group owns the cancelation source whose token is passed to each operation. When any operation completes, the group cancels the token then waits until all operations are complete before continuing, thus guaranteeing no operations are orphaned and left running.

An example of the "structured concurrency" pattern: https://github.com/StephenCleary/StructuredConcurrency, though I expect to implement it differently (need to account for returning values like Promise.All<T> and Promise.Merge<T1, T2>, which that library doesn't do).