Notifications from clients arrive on I/O completion ports. Blocking these threads causes deadlocks and/or severe performance penalties. Therefore, allowing clients to close over enumerables, or synchronous functions of any kind within their queries MUST not be permitted. Testing these features over the years has often resulted in deadlocks and unexpected behavior, and frankly it's much harder to debug a client query with them in place.
Furthermore, considering all of the great async support that has come to be since having written this framework, it only makes sense to avoid sync callbacks altogether.
Therefore, only the following scenarios SHOULD be supported:
- Closing over any
IObservable<T>, or any type that implements IObservable<T> (e.g., Subject<T>)
- Closing over any local function that returns
IObservable<T>, or any type that implements it.
a. Note that this is acceptable because the function call from the server to the client can be async since an observable proxy can be created on the server. After all, the call to Subscribe is inherently async, thus the server can continue executing the query and call Subscribe on the proxy observable, while the duplex mechanism asynchronously sends the invoke message to the client and calls Subscribe on the client-side.
- Closing over any
Task or Task<T>.
- Closing over any local function that returns a
Task or Task<T>.
- Closing over any
IAsyncEnumerable<T> -- (For future consideration).
- Closing over any local function that returns
IAsyncEnumerable<T> -- (For future consideration).
Notifications from clients arrive on I/O completion ports. Blocking these threads causes deadlocks and/or severe performance penalties. Therefore, allowing clients to close over enumerables, or synchronous functions of any kind within their queries MUST not be permitted. Testing these features over the years has often resulted in deadlocks and unexpected behavior, and frankly it's much harder to debug a client query with them in place.
Furthermore, considering all of the great async support that has come to be since having written this framework, it only makes sense to avoid sync callbacks altogether.
Therefore, only the following scenarios SHOULD be supported:
IObservable<T>, or any type that implementsIObservable<T>(e.g.,Subject<T>)IObservable<T>, or any type that implements it.a. Note that this is acceptable because the function call from the server to the client can be async since an observable proxy can be created on the server. After all, the call to
Subscribeis inherently async, thus the server can continue executing the query and callSubscribeon the proxy observable, while the duplex mechanism asynchronously sends the invoke message to the client and callsSubscribeon the client-side.TaskorTask<T>.TaskorTask<T>.IAsyncEnumerable<T>-- (For future consideration).IAsyncEnumerable<T>-- (For future consideration).