-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Support IAsyncEnumerable returns in SignalR hubs #6791
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
af62ffc
to
25e5b5d
Compare
src/SignalR/server/Core/src/Internal/AsyncEnumeratorAdapters.cs
Outdated
Show resolved
Hide resolved
25e5b5d
to
7661d7d
Compare
931c470
to
c6d06e4
Compare
c6d06e4
to
42587e4
Compare
Waiting on #7005 |
97c134d
to
522a741
Compare
{ | ||
// Assume that this will be iterated through with await foreach which always passes a default token. | ||
// Instead use the token from the ctor. | ||
Debug.Assert(cancellationToken == default); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
REVIEW: The reason we have to wrap IAsyncEnumerators with non-value-type generic parameters instead of just casting is because we iterate using await foreach
which doesn't support flowing a CancellationToken through GetAsyncEnumerator. If we manually iterated over the enumerator, we could save ourselves wrapping in most cases.
So should we manually iterate instead of wrapping the GetAsyncEnumerator call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are the only consumer of the IAsyncEnumerable<object>
btw
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we could loop over MoveNextAsync()
manually and avoid the BoxedAsyncEnumerator
? That sounds nice :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes we should optimize
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could have said something before I merged. It was a while loop that manually called GetAsyncEnumerator/MoveNextAsync until you asked me to change it to await foreach
@davidfowl 😆
I figured didn't care about the allocation since a bunch of other allocations happen in this code path anyway. I created #7960 to track this with an XS tag. If we want to change this, it's not difficult.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I care, lets fix it in preview4. Assign it to yourself 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm glad you care 😉
0d00933
to
31c46d8
Compare
I was hoping typeof(T).IsValueType would get evaluated during JIT compilation which would allow for dead code elimination, but alas: https://github.com/dotnet/corefx/issues/16217
- Allow hub methods to also return types implementing IAsyncEnumerable
- Flow CancellationToken to IAsyncEnumerable.GetAsyncEnumerator
31c46d8
to
1cf98a5
Compare
I'm waiting for the dotnet SDK to get updated in this repo so I can target C# 8 in our test projects. I'll add tests once we have it.
#5357