Feb 7, 2023 · 23 comments · 62 replies
{{actor}} deleted this content .
-
📢 UPDATE Rx .NET 6.0 is now available.
📢 UPDATE FREE Introduction to Rx.NET eBook is now available Online, On GitHub, as PDF and as EPUB
Our aim is to continue to promote Reactive Programming as one of .NET’s Superpowers. At a very high level, we’d like to reverse the public opinion that “Rx (.NET) is dead”. How can we achieve this?
Below is our high-level backlog covering the v6.0 and v7.0 releases, and we will flesh out each item with associated links to issues / discussions / PRs, and can amend based on feedback from the community.
To summarise:
Ian Griffiths (@idg10) and Howard van Rooijen (@HowardvanRooijen) from endjin have volunteered to become project maintainers.
These tasks are required to enable this transition:
net6.0
TFM packages ( Add Rx.NET 2023 roadmap, and tooling update ADR #1879, Upgrade to supported TFMs and SDK versions #1882)SynchronizationContext
causes different code path to run; tests should run both with and without SynchronizationContext
📦https://www.nuget.org/packages/System.Reactive/6.0.0-preview.1
📄https://github.com/dotnet/reactive/releases/tag/rxnet-v6.0.0-preview.1
📦https://www.nuget.org/packages/System.Reactive/6.0.0-preview.9
📄https://github.com/dotnet/reactive/releases/tag/rxnet-v6.0.0-preview.9
📦https://www.nuget.org/packages/System.Reactive/6.0.0-preview.13
📄https://github.com/dotnet/reactive/releases/tag/rxnet-v6.0.0-preview.13
📦https://www.nuget.org/packages/System.Reactive/6.0.0-preview.16
📄https://github.com/dotnet/reactive/releases/tag/rxnet-v6.0.0-preview.16
📦https://www.nuget.org/packages/System.Reactive/6.0.0
📄https://github.com/dotnet/reactive/releases/tag/rxnet-v6.0.0.1
📖https://endjin.com/blog/2023/05/rx-dotnet-v6-released
📦https://www.nuget.org/packages/System.Reactive.Async/6.0.0-alpha.3
📄https://github.com/dotnet/reactive/releases/tag/asyncrxnet-v6.0.0-alpha.3
We thought it would be useful to track the amount of time we're dedicating to this endeavour.
January 2023
February 2023
March 2023
April 2023
May 2023
June 2023
July 2023
August 2023
September 2023
October 2023
November 2023
December 2023
January 2024
February 2024
March 2024
April 2024
May 2024
June 2024
July 2024
August 2024
September 2024
October 2024
November 2024
December 2024
April 2025
May 2025
June 2025
July 2025
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
All reactions{{actor}} deleted this content .
-
I came from unity background and I would like to voice that real time app like 3D game is very much needed the reactive system. Event is everywhere and UI can have many state to fabricate together with game state
Also I have some work with js so I wish that every RX platform should have same name for same functionality, especially not make conflict name (same name but have difference behaviour) and I would prefer that RX specific operator in dotnet should align with other platform, even it will cause breaking change
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
15 replies
-
If that was the case then that's very ok. But one things I am wonder is, which is the really correct definition of throttle
?
Which behaviour act more like a real life throttle
?
I am not really sure why they have difference implementation but one thing is, if I remember correctly, the js implementation was also released from Microsoft too. And I suspect that they change the name of operator in js because that was the more correct definition of operator. That was one reason I think Rx.Net should change their operator name
Beta Was this translation helpful? Give feedback.
{{actor}} deleted this content .
-
The obvious example of "a real life throttle" is the kind common in many automobiles (for this discussion I'm ignoring modern sophisticated fuel injection systems that don't require a throttle) in which there is some sort of control signal (e.g. the gas pedal in a car) which adjusts the effective cross sectional area of a pipe through which a gas (or fuel/air mixture) is flowing.
From a user perspective, the crucial feature of throttles of this kind is that they let you change the flow rate dynamically. (E.g., press foot down to accelerate harder. Raise root to reduce acceleration.)
More subtly, but significantly, they open the big can of worms labelled "back pressure". Physical throttles don't work by addressing flow rate directly—with an internal combustion engine, the flow rate through the throttle for any given throttle setting will vary enormously based on engine speed. (For any throttle setting and engine load there will be an equilibrium condition, so you could say that there is a flow rate for that setting...except that equilibrium flow rate for a particular throttle setting varies by load: it will be lower if you're going uphill vs flat; all other things being equal the equilibrium flow rate for a single throttle setting will be different for each gear.) What the throttle is actually doing is changing the relationship between engine inlet manifold pressure and the air pressure inside the air intake. In a simplified model you could look at a throttle as applying a dynamically adjustable scale factor to the back pressure on its output side (engine inlet manifold) and the back pressure on its input side (air filter). But however you look at it, real throttles don't work by imposing a particular flow rate.
The RxJS throttle doesn't appear to be anything like that. As far as I can see, it differs from a "real life throttle" in two critical respects:
So if the accuracy of physical analogies is a factor, we should submit a bug in the RxJS repo telling them they should either have called it "restrictor plate" because the lack of dynamic adjustability makes that a closer physical analogy than "throttle", or possibly "flow rate limiter" because its operation is actually quite different from either a throttle or a restrictor plate, in that what it actually does is measure flow rate and block flow if and only if it exceeds a specified rate.
(Actually, maybe I shouldn't have ignored modern throttle-less engine designs. The RxJS throttle is, ironically, slightly closer in operation to a "no throttle" engine than it is to a throttle. Modern engines without a throttle meter the gas flowing through them and inject precisely metered quantities of fuel based on the control inputs. It's not a precise analogy for how RxJS's throttle works, but it's probably a bit closer than an actual throttle because it directly controls the fuel flow rate.)
...but seriouslyOK, that was fun because I'm fascinated by automotive technology but it probably doesn't help the discussion very much. The main point is that neither RxJS's throttle nor Rx.NET's throttle bear very much resemblance to a physical throttle, having one major difference (the absence of a dynamic control input) and one more subtle difference (metering vs the complex effects of cross-sectional area restrictions in gas flow).
So for that reason I don't think asking which is more like a real life throttle gets us anywhere.
I think there are really only three considerations here:
I would consider 2 to be a "nice to have" and 1 to be "highly desirable, only to be broken if there are really good reasons." Unfortunately, we can't have both because Microsoft decided to break 2 when they made RxJS because they made its throttle do something different (presumably because of 3). I don't think 2 is a strong enough reason to overrule 1 in this instance.
3 is a slightly more compelling argument to me: Rx.NET's Throttle is just a bit strange, and all the places I thought I might want to use it, it has turned out not to be the thing I really wanted, and I've had to construct something out of other operators instead.
However, 3 would be easily addressed by adding a new operator that does what we want, instead of changing the behaviour of an existing one. That would address 1 and 3. I think that's better than breaking 1 in order to address 2 and 3, because the benefits of 2 seem to me to be pretty small in practice, and we don't need 2 to fix 3.
Beta Was this translation helpful? Give feedback.
-
Hi @laurentkempe! Do you have any information about the changes you needed to make? It would be an interesting insight for us.
While porting our WPF application to .NET 5/6 and Rx 5 we had to change the TargetFramework
to net5.0-windows10.0.19041
for our WPF application csproj, see #1423.
For the .NET 7 migration, we had to go from <TargetFramework>net6.0-windows10.0.19041</TargetFramework>
to <TargetFramework>net7.0-windows</TargetFramework>
. Doing so meant to miss the DispatcherScheduler
, because of the way the things are bundled in the Rx nuget:
net5.0-windows with DispatcherScheduler
net5.0 without DispatcherScheduler
So, we had to insource some part of Rx source code related to Windows into our code base; System.Reactive.Concurrency.DispatcherScheduler
, System.Reactive.Constants_WindowsThreading
and System.Reactive.Linq.DispatcherObservable
.
I think that #1847 would help us to remove again the Rx source code from our code base.
Beta Was this translation helpful? Give feedback.
-
What was the reason for going to net7.0-windows
instead of net7.0-windows10.0.19041
? I was under the impression that when you omit the version in an OS-specific TFM, it implied some minimum version. The docs at https://learn.microsoft.com/en-us/dotnet/standard/frameworks#os-version-in-tfms say:
When an OS-specific TFM doesn't specify the platform version explicitly, it has an implied value that can be inferred from the base TFM and platform name
Frustratingly, they don't appear to publish a list of the inferred version for any given TFM, but when I use the MS Build structured log viewer to discover this by inspection, it generally seemed to default to a really old (like, Windows 7) versions of Windows.
So my understanding of the meaning of your net7.0-windows
isn't that its a different sort of TFM than net7.0-windows10.0.19041
. It's that it is equivalent to one particular OS-version-specific TFM (but the docs don't tell you which one). Or did something change in .NET 7.0 that I've missed?
I've not yet got to the bottom of why Rx specifically chose Windows 10.0.19041 for its Windows-specific TFM. The change recently merged to main
retains exactly the same SDK version for the net6.0
variant, but you've got me wondering whether we should be looking at some different Windows-specific TFM. After all, #1847 is only going to help you if we choose TFMs for the Windows-specific packages that your app will be able to consume. So if we retained the current windows10.0.19041
presumably that would break you for exactly the same reasons Rx 5.0 is also not working for you?
Beta Was this translation helpful? Give feedback.
-
Please do something about it. We recently faced the same issue, after upgrading to latest stable Rx version we found Dispatcher related methods, specifically ObserveOnDispatcher
is missing so we had to do exactly the same thing as done by @laurentkempe , manually adding these platform specific extension classes into our solution (which works fine).
I've read your previous post related to future Rx packaging, i believe separate platform specific packages with a core package is the ultimate solution. but you guys are the pros and know better.
Huge appreciation for the Rx team. Thanks :)
Beta Was this translation helpful? Give feedback.
-
Thanks a bunch for stepping in as maintainers @HowardvanRooijen and @idg10! It’s great to see new sparks of life here and not having the project rot in silence.
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
0 replies
{{actor}} deleted this content .
-
I'm surprised I've not seen more examples of using RX.NET with dotnet/iot too. You might want to reach out to them!
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
1 reply
-
100% If you look at any of Ian's Rx talks - one of the first demos is an IoT scenario (where the "thing" is a marine vessel sending AIS messages). In another he uses a Pulse Oximeter.
Beta Was this translation helpful? Give feedback.
{{actor}} deleted this content .
-
Throwing out an idea: it would be good to cede the IX operators back into the BCL given the first class support for IAsyncEnumerable<T>. There’s been many discussions about why we’re not adding async LINQ to the BCL and it’s because this package already does that. While I have no problems in general with an IX dependency, it feels like something that should be built in now given the in the box (including compiler support) for IAE.
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
7 replies
-
Yeah some consolidation of these types would be great. In my mind, standard LINQ operators for IAsyncEnumerable
, as well as the definitions of IAsyncObservable
and IAsyncObserver
belong to the BCL. Maybe we should take this into consideration when publishing the first async packages, and put them in the namespaces they should be in, so that existing code doesn't break in case MSFT decides to include these types in some future version.
Beta Was this translation helpful? Give feedback.
-
In that regard: IObservable ist already in the standard lib. It would be really cool to have the standard LINQ operators, like Select, Where etc. in the standard lib as well and have this package for all the fancy extended stuff.
While I also see that as having a possible advantages I keep the focus on how to manage the structure of Rx.net itself as well a how that's split up into assemblies.
Other with what you proposed would be:
I would personally be in favour of possible moving a few select interfaces over but for now I don't think that I'd be for moving those operators.
Beta Was this translation helpful? Give feedback.
-
First of all, I don't think @davidfowl was offering to have the .NET runtime library take ownership of Rx operators. It makes sense for IAsyncEnumerable
because that's such an important interface that C# itself has baked in support for it. IObservable<T>
and IObserver<T>
aren't treated as being as important. (And much as I love Rx, I'd have to concede that they probably aren't as important...)
Secondly, I agree with @Fijo that even if the .NET runtime library team were open to taking ownership of parts of Rx too, the scheduler mechanism would likely be too much for them to swallow. While IObserver/able<T>
are fundamental abstractions, Rx's scheduler model is arguably an opinionated approach. For example, Reaqtor defines its own IScheduler
which does a similar job but has a number of differences. That alone tells you that there's more than one way to define even just the relevant abstractions, so I don't think I'd want Rx scheduling to be in the runtime library. And that would rule out a large chunk of Rx.
So we'd end up with Rx being split, which I think would just cause confusion, even if the .NET team were up for taking on parts of Rx (which I don't believe they are).
Beta Was this translation helpful? Give feedback.
-
Although I know @colombod has said several times that he would love (a) IScheduler to be in the BCL partly because virtual time abstractions are so useful.
Beta Was this translation helpful? Give feedback.
-
BCL is developing too slowly.
Beta Was this translation helpful? Give feedback.
-
Let me say first thank you and that I think you're doing God's work here. My question is how does all this fit in with Microsoft's Reaqtor project?
…On Wed, Feb 8, 2023 at 6:34 AM David Fowler ***@***.***> wrote: Throwing out an idea, it would be good to cede the IX operators back into the BCL given the first class support for IAsyncEnumerable<T>. There’s been many discussions about why we’re not adding async LINQ to the BCL and it’s because this package already does that. While I have no problems in general with an IX dependency, it feels like something that should be built in now given the in the box (including compiler support) for IAE. — Reply to this email directly, view it on GitHub <
#1868 (comment)>, or unsubscribe <
https://github.com/notifications/unsubscribe-auth/AZ6ZGLBD72TZVMTAMDSS3QLWWOVIVANCNFSM6AAAAAAUTSXILU> . You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
1 reply
-
This is an interesting question. The Rx bits of Reaqtor (specifically, the Reaqtive
libraries) originated as an evolution of Rx. You could think of them as one possible direction for an Rx.vnext if such a thing were not constrained by backwards compatibility. Reaqtive
adds some things that Rx does not have (most notably a way to persist any accumulated state built up by operators, making it possible to reconstruct a new subscription that is in exactly the same state as a previously persisted one).
There are enough differences that it's not currently clear what a path to reunify these two libraries would look like, so we currently don't have plans for such a thing. In particular, async has major complications in a world in which you want to be able to halt running Rx subscriptions temporarily to snapshot their state. But one of our main goals for Rx is to get the currently experimental Async Rx code to a proper release, and trying to realign with Reaqtive
would lkely delay that goal.
So in practice these two flavours or Rx are likely to coexist.
Beta Was this translation helpful? Give feedback.
-
More and more software is becoming distributed. I'm having a hard time seeing RX getting more adoption unless it can help make streaming/messaging better (over the stuff .NET already provides).
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
3 replies
-
I would say that Rx makes it incredibly easy to work with streams / messaging; it was created by The Cloud Programmability Team back in 2011 for these very scenarios.
A good example would be a demo we wrote to showcase how to process real time marine vessel data:
https://github.com/ais-dotnet/Ais.Net.Receiver
The combination of modern C# / .NET makes it incredibly easy to go from a compact binary protocol to a high level programming model (in a Zero Allocation way):
Beta Was this translation helpful? Give feedback.
{{actor}} deleted this content .
-
Low-level messaging for backed solutions isn't much different from in-process solutions. When I think "distributed" I think globally accessible APIs, microservices, message buses, heterogeneous data sources and targets. In other words, I think "enterprise".
Beta Was this translation helpful? Give feedback.
{{actor}} deleted this content .
{{actor}} deleted this content .
-
I find the Rx pattern really powerful and it is fantastic news that this project is in the process of being revived. "At a very high level, we’d like to reverse the public opinion that “Rx (.NET) is dead”. How can we achieve this?" Unfortunately, any library that lands up 2 major releases behind is "dead". The only way to reverse that opinion is to make the project current and as you are doing provide a convincing Roadmap.
Having been "dropped" by Rx.NET once I am now reluctant to use it support any major work, unlike RxJS which has remained current and has been prepared to make necessary breaking changes (yes they were really irritating at the time).
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
5 replies
-
The only way to reverse that opinion is to make the project current and as you are doing provide a convincing Roadmap.
And some marketing is required. Do videos and show how it can be used in many different scenarios. I use RX in a couple of projects for comms over TCP and UDP but finding info on doing this properly was not easy. Also show how to use it with different projects and integrations: MS Orleans, Akka.net, etc...
Beta Was this translation helpful? Give feedback.
-
I can empathise that it's frustrating to not have a version that not "up to date". I would say that in the last 5 years .NET has been in a very unique situation transitioning from .NET Framework to .NET and it's made life incredibly complicated. Not just for Rx - we have over 50 OSS projects and it has taken a vast amount of effort to keep these up to date and dealing with the shifting requirements of .NET / .NET Framework / .NET Standard / SDKs / Build Pipelines etc. I think we're entering a phase of relative stability where dealing with major .NET version increments is actually a relatively straightforward endeavour.
@mika76 - one thing I think would really help is the community sharing examples / recipes of how they're using Rx - examples of using it for TCP / UDP would be great. I would love to move Rx over to the Reactive-Extensions Org, so that we can have multiple repos, including lots of samples / recipes.
Beta Was this translation helpful? Give feedback.
-
Unfortunately, any library that lands up 2 major releases behind is "dead".
The first thing to point out is that if you create a .NET 7.0 project today and add a reference to the current version of System.Reactive
it works. A library does not need to target the latest .NET version in order to run on the latest version of .NET.
On a related note, the fact that Rx is on version 5 does not have anything to do with .NET version numbering. By coincidence, the version numbers briefly aligned—version 5 of Rx happened to coincide the .NET 5.0. But there is no intention to tie System.Reactive
version numbering with runtime versions, as happens with the various Microsoft.Extensions.*
packages.
Incidentally, this issue is a current difference of opinion between @HowardvanRooijen and me:
(As it happens, I think developers are presently justified in thinking that Rx is at best moribund, but that this has more to do with the release date of the most recent version, the lack of activity in this repo, and the ever-growing backlog of requests. My hypothesis is that if we address all of those things—if there are seen to be recent releases, active work to maintain alignment with current build tooling, and positive responses to the outstanding issues—this will be a convincing argument that it's not in any way behind. If we do all of that, my view is that the version of .NET the TFMs refer to is irrelevant, and my hope is that this will be clear to everyone else.)
And to clarify, when I talk about targets here, I'm talking about the consumable NuGet packages. It is our intention that all test projects in the repo should target the very latest version of .NET available at all times. So when .NET 8.0 ships, we will want to get tests that validate correct operation on .NET 8.0 in place as soon as possible (regardless of the libraries' state target frameworks).
In short, we will fully support the latest available platform, but that doesn't mean the libraries will target that platform.
There are pros and cons to targeting newer TFMs.
Pros:
As an example of pro 1, a different open source library that we maintain has net7.0
builds because there are ways it can take advantage of static interface members to improve performance. If such a possibility were identified for Rx, that would be a strong incentive to produce builds that target the relevant TFM. As far as I know, this is currently a hypothetical consideration for Rx.
My view is that in the absence of any pro 1 type reasons, pro 2 is a weak reason to add newer TFMs.
Cons:
Regarding con 3, one option is to say ".NET Core 3.1 is out of support, so it's totally OK to abandon anyone still using it" but I think it's important to remember that a non-trivial number of projects get stuck on unsupported versions of things for various reasons outside of the developers' control. While it is possible to take the purist view, my view is that we shouldn't abandon those developers if the only justification is perceived freshness. (The principle here is not to throw existing users under a bus with scant justification. So this logic wouldn't extend to saying that we should target even older versions such as netcoreapp2.0
. It's simply an argument against moving to the newest version for the sake of targeting the newest version.)
And con 3 notwithstanding, cons 1 and 2 mean that the default policy should be not to multiply the number of different builds of what is effectively the same thing, unless we have a really good reason. (This suggests that if it were possible, we'd have just a single build where possible. Currently, the support for UWP combined with the way the various libraries are structured means this is not possible, but I think it is at least worth asking whether reinstating the old "platform enlightenments" concept that Rx 2.0 had would enable a single netstandard2.0
target for most of Rx.)
To be clear, my current position is that if suitably compelling "con 1" type opportunities are identified, then it's worth adding corresponding targets. (Although even then I would target the oldest possible TFM. E.g., if we were to find useful applications of static interface members, to pick one example, we would produce a net7.0
target, but when .NET 8.0 ships later this year, we would continue to target net7.0
and not net8.0
. The only reason we'd have a net8.0
target is if .NET 8.0 offers some new functionality that Rx itself wants to use.)
It's worth finishing by just clarifying a couple of things, because the whole situation around TFMs can be a bit confusing. So to be clear, the following are misunderstandings:
.net7.0
can happily use libraries that target netcoreapp3.1
.netcoreapp3.1
and net5.0
TFMs are out of support." Not so. The corresponding runtimes (.NET Core 3.1, and .NET 5.0) are out of support, but the TFMs continue to be supported. For example, it is fully supported to use a netcoreapp3.1
library on .NET 7.0.Span<T>
and related types back in .NET Core 2.1—those offered amazing performance benefits to some kinds of code, but only if you made significant changes to your code)Beta Was this translation helpful? Give feedback.
{{actor}} deleted this content .
-
I think they meant another problem. That it lacks the features that net6.0 / net7.0 offers, not only performance related. For example, trimming / linker-friendly support #1683.
For net6.0 the library should be marked with <IsTrimmable>true</IsTrimmable>
(for net7 it's not necessary) for it to work out of the box. If the library is using Type
(reflection), then you also need to annotate the library correctly. This is crucial for Blazor WASM applications. Workarounds exist to force the trimming for the library or if something got broken you can use BlazorLinkerDescriptor
, but most developers don't know about it.
In my opinion, most people expect that such important lib as Rx should follow the latest .NET trends - trimming, source generator, etc. Though, it's not always a good idea and necessary as you mentioned.
Beta Was this translation helpful? Give feedback.
-
We added that IsTrimmable
setting (along with a load of attributes to annotate the parts of Rx that aren't really going to work with trimming—mostly the expression-tree-based IQbservable
bits, because those in turn depend on .NET's own IQueryable
implementation for IEnumerable
, which declares itself to be unsuitable for trimming, but also one of the reflection-driven mechanisms for handling .NET events turns out to be non-trim-compatible) in #1906 and it's in the 6.0.0-preview.9 preview release.
I built an experimental Blazor-based app that makes very simple use of Rx. Using the v5.0.0, we can see the lack of trimming meant that Rx adds about 1.5MB to the size, but using this new trim-enabled preview, it reduced System.Reactive.dll
down to about 32KB. So that looks like it's working.
Beta Was this translation helpful? Give feedback.
-
On the subject of source generators - does anyone have any links to issues/request/discussion of scenarios where they would be useful?
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
4 replies
{{actor}} deleted this content .
-
No - not in general; specifically in the context of their use within the Rx framework. We've seen a couple of mentions recently in the context of Rx, but no-one has provided a use case that we don't support. There were obvious use cases in e.g. System.Text.Json
serialization, or the Regex
support, but they are not jumping out at me within the Rx framework.
Beta Was this translation helpful? Give feedback.
-
Yeah I can't think of anything either.
Beta Was this translation helpful? Give feedback.
-
Hmm, there is System.Linq.Async.SourceGenerator
(#1575) which uses old ISourceGenerator
, the IIncrementalGenerator
is more preferable now.
In the comments bartdesmet also mentioned where it could be used.
Beta Was this translation helpful? Give feedback.
-
I looked into Rx/Ix a few times, and the biggest hurdle by far was figuring out which namespace and NuGet package contained a specific API. As I remember it, there are a bunch of NuGet packages not mentioned at all in the README. There are also mentions of breaking changes from earlier versions that are already surpassed by new breaking changes.
Maybe other people use the libraries just fine, but for me it was an all round confusing experience and I was/am reluctant to try again.
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
4 replies
-
That's interesting—evidently I'm suffering from "the curse of knowledge" here.
Literally the first thing in the readme that shows up when you go to https://github.com/dotnet/reactive is a table that includes a row linking to the latest packages produced by this repo. It has exactly two entries: one for Rx, and one for Ix.
That Rx one, the button that looks like , takes you to the package you need.
So it's really interesting to me that even though the very first thing in the readme directly answers one of your two questions, there's something about the way that we've presented this information that means you didn't see that. (And I consider this to be our fault, not yours just to be clear. I'm not saying that just because it was right there you should have seen it. I'm just wondering how we might improve this.)
I'm wondering if part of the problem here is that the readme starts with a rather esoteric discussion of version history that starts with the version from 2018 (v4), then moves to v5, before going on to say a bit more about v4, then some stuff about v3, which is really old... I'm not convinced that really belongs on the front page readme...
I'm wondering if we kept that table at the top, but maybe directly after that added a Getting Started section with something like this:
mkdir TryRx cd TryRx dotnet new console dotnet add package System.Reactive
and then said to put this in your Program.cs
:
using System.Reactive.Linq; var ticks = Observable.Timer( dueTime: TimeSpan.Zero, period: TimeSpan.FromSeconds(1)); ticks.Subscribe( tick => Console.WriteLine($"Tick {tick}")); Console.ReadLine();
and then tell them to run dotnet run
.
That gets you up and running with a very simple Rx example. Do you think that would have worked for you?
Beta Was this translation helpful? Give feedback.
{{actor}} deleted this content .
-
I guess it depends on the path you take to arrive at this repo. If I remember correctly, I was looking for some specific System.Linq.Async
method after seeing it recommended somewhere to solve a problem. So I added https://www.nuget.org/packages/System.Linq.Async but couldn't quite figure out how to get started, still being somewhat new to the whole async iterators stuff.
The package points to this repo as its source, and as you say, the first thing you see is packages for Rx and Ix. At that point I had no idea what those packages are or how they are related to System.Linq.Asyc
. The readme continues talking about breaking changes, and unfortunately it only added to my confusion.
Then I attempted to just dive into the source, and managed to figure it out after finding the Ix.NET/Source/System.Linq.Async/System/Linq/Operators
directory.
A bit later I needed some specialised LINQ method and again my searches pointed me to this repo. Still not knowing very well what Rx and Ix are, I think I tried to figure out which of the System.Reactive.*
/System.Interactive.*
packages I needed (you publish more than just the 2 main packages under https://www.nuget.org/profiles/rxteam). Maybe that was a critical mistake by me and I should have just added one of the two main packages.
I think the changes you suggest would help for sure, in addition to an example for System.Linq.Async
.
Beta Was this translation helpful? Give feedback.
-
OK, so the short "getting started on Rx" section I suggested would have been no use at all.
That suggests that what we really need is a succinct description of the things that are in this repository. It contains:
System.Reactive
)IAsyncEnumerable
(aka System.Linq.Async
)System.Interactive
)These are somewhat different things (although they're conceptually united under "LINQ to everything" and more specifically "LINQ over sequences of things" which is why all three are in the same repo). So we could add a brief "What's in here, what's it for, and where do I look next to find out more?" section, answering those questions for each of the three things above. Would that have been helpful, do you think?
Beta Was this translation helpful? Give feedback.
-
Since that got a few thumbs up, I've created an issue for this: #1881
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
6 replies
{{actor}} deleted this content .
-
My suggestions:
This allows UWP to remain "supported", without creating the burden of working around all the problems it creates. As mentioned, there are some Windows APIs only UWP apps can consume, but I feel the number of developers that are using them, using Rx.NET, and need/want more than critical Rx.NET bugfixes is likely to be vanishingly small.
Meanwhile, the number of Rx.NET users that don't care about UWP support in future releases, but rather want to see Rx.NET flourish as quickly as possible is going to be something like 99.99%+.
I'm unsure how this would impact projects that depend on Rx.NET and currently support UWP. The only one I can think of is ReactiveUI.
Beta Was this translation helpful? Give feedback.
{{actor}} deleted this content .
-
Regarding ExecutionContext
, We're certainly prepared to look at it again, although I would say that I we would only be able to consider solutions that did not break backwards compatibility, and which imposed no performance overhead on people who did not want this.
I haven't really understood how can you achieve this with
IScheduler
.
I suppose what people who suggest this are imagining is that a scheduler would capture the execution context at the point where work is scheduled. However, there seems to be a problem with that: in general there isn't a one to one relationship between the items that flow from observable to observer, and scheduling of work items. For example, if you use ObserveOn
, items are delivered to an internal queue, and there is no per-item scheduling of work. Instead, a single 'drain' operation is scheduled, which will run until the queue is empty. So 100 calls to the ObserveOn
's observer's OnNext
might well be processed in a single scheduled work item.
As far as I can tell, the thing people seem to be looking for is that the ExecutionContext
in place when they pushed something into Rx (e.g. when calling OnNext
on a Subject<T>
) should be used when that same item is next processed by user code (e.g., when the OnNext
of our own subscriber somewhere downstream receives the same item). But Schedulers don't necessarily get asked to do things at a 'per-call-to-OnNext
' level, so I don't think they could provide an automatic solution to this.
There are also conceptual problems even before schedulers get involved. There's the question of what happens when things get combined. What's the correct behaviour for Buffer
in cases where every single item in a batch originated from a different ExecutionContext
? What's the correct behaviour for a temporal join?
Obviously I've not spent a huge amount of time thinking about this, but on the face of it, it seems like the only way to deal with these problems would be to flow the execution context through explicitly. You could imagine something like this:
public static class ContextPropagationExtensions { public static IObservable<(T Value, ExecutionContext? Context)> WithContext<T>(this IObservable<T> source) => source.Select(x => (x, ExecutionContext.Capture())); }
...and some corresponding OnContext
that turns an IObservable<T Value, ExecutionContext? Context)>
back into an IObservable<T>
, promising to execute each call to OnNext
on the specified ExecutionContext
. That would enable something like this:
source .WithContext() // ExecutionContext captured for each item here .Delay(TimeSpan.FromMilliseconds(1)) .OnContext() // Downstream OnNext invoked via capture ExecutionContext here .Subscribe(OnNextDelayed);
Or you could model it more like the Timestamp
operator, and have the return type be, say, IObservable<ValueWithExecutionContext<T>>
. (This immediately suggests a more generalized idea of ValueWithContext<TValue, TContext>
so you could flow any sort of context.) A problem with that is that it wouldn't flow context for errors or completion. You could perhaps solve that with an entire parallel implementation based on some hypothetical IContextualObserver<T>
in which all three methods take an additional context argument, but adding an entire parallel LINQ implementation seems like a fairly massive undertaking. Or maybe you could deal with OnError
and OnCompleted
by reifying everything in the manner of Notification<int>
.
Any of those solutions suffer from the problem that it you can't just insert a magic operator mid stream that makes it all work, because it has an impact on any code downstream of that. (Everything that was previously referring to, say, x
now has to use x.Value
). Then again, if your goal is to lift stuff into an "event stream with context" space in order to pass through context-destroying operators such as Delay
, and then lower it back into normality downstream of them, maybe you don't care what the 'with context' space looks like.
So solutions may be possible. (And it also seems like they could be built as a layer on top of Rx by anyone, so they wouldn't need to be a core part of Rx.)
We're certainly open to discussions and further thought.
Beta Was this translation helpful? Give feedback.
-
Regarding @kmgallahan 's suggestions:
Next major release = 6.0 which drops support for UWP and sorts out the WinForms/WPF file baggage issue
Make a minor 5.1 release that drops the UWP testing project, but leaves open the option to slip in critical bugfixes to UWP users from the 6.0+ releases
Just to check I've understood the difference between this and our proposal, let's start with the "v.next" described in the Rx.NET/Documentation/adr/0001-net7.0-era-tooling-update.md
ADR compared to your suggested v5.1. I think the main difference is: we are proposing to solve the UWP test project problems by moving to the MSTest
framework, whereas you appear to be proposing to deal with that by not running any tests against UWP.
If we are still to support UWP in some way, I think it's vital that we run tests against it. Your v5.1 suggestion seems to be designed expressly to provide a route for ongoing UWP support, so I don't understand why you would remove the UWP test project. How could we be certain that we hadn't broken anything on UWP if we don't test on UWP?
Moving onto our "v.next.next" which corresponds to your suggested v6.0, it's pretty close to our current idea, but with one particularly significant difference: instead of dropping support for UWP entirely, our goal would be to isolate that support. (So we would remove all the uap10.0.x
targets from everything except for one or two UWP-specific projects. We might even move that code into a separate repository, if we could work out a satisfactory way to run all the same tests on UWP that we run on other runtimes.)
I feel the number of developers that are using them, using Rx.NET, and need/want more than critical Rx.NET bugfixes is likely to be vanishingly small.
This is a conjecture. We can't really know this. I would argue that one advantage of our suggested approach, in which both v.next and v.next.next continue to support UWP, but where v.next.next would require UWP developers to reference a different package if they genuinely need the UWP-specific functionality, is that we'd be able to learn something about how many UWP developers are really using this based on how many complaints we get about the change. If we hear absolutely nothing, then perhaps your feeling is correct (and maybe the version after that could drop UWP entirely). But if we hear complaints, then we'll know UWP still isn't dead yet.
Beta Was this translation helpful? Give feedback.
{{actor}} deleted this content .
-
we would only be able to consider solutions that did not break backwards compatibility
Absolutely.
Here are just a few use cases with ExecutionContext
. Some libs use AsyncLocal
, for example: JetBrains.Lifetime, OpenTelemetry, there are DI-containers that prefer The Ambient Composition Model over The Closure Composition Model.
The last case is what I personally encountered. I use ambient context to store some tcp connection information since I do not want to pass this information all around the code and for this I use SimpleInjector's scoping(or I could use AsyncLocal myself). I prefer to write the UI in a reactive manner with ReactiveUI and if you make something like this:
public class ExampleViewModel : ReactiveObject { private readonly SomeScopedHandler _someHandler; //Inside the ReactiveCommand is using Subject<T> public ReactiveCommand<Unit, Unit> CompleteCommand { get; } public ExampleViewModel() { CompleteCommand = ReactiveCommand.Create(OnComplete); } public void OnComplete() { //When we get this event the ExecutionContext is broken someHandled(...); //Some scroped handler that will take the ambient context information. Since ExecutionContext is incorrect the SimpleInjector will throw exception. } }
You will get problems.
Beta Was this translation helpful? Give feedback.
{{actor}} deleted this content .
-
How could we be certain that we hadn't broken anything on UWP if we don't test on UWP?
I'm uncertain of how many outstanding UWP-specific bugs are in the backlog. A quick issue search for 'UWP' has 4 results, 2 of which don't appear to be bugs. So the concern of maintaining a UWP test suite is to ensure bug fixes that pass .NET / Framework tests also work when running on .NET Native.
In a perfect world, there would be ongoing UWP support for bug fixes and new features, with a full test suite to ensure everything works flawlessly with (the long abandoned) .NET Native.
However, in a practical world, it takes time and effort to get everything done. Converting the test suite away from XUnit, getting them to build & pass, maintaining it for years, writing new tests against every new bug and feature, splitting out UWP support into a new repo, and maintaining said repo & builds is all a non-trivial amount of work.
RX.Net is now a community-supported project. So unless the community expresses a strong interest in UWP support, and/or volunteers step up to actually get all that work done (both in a timely manner for the next release, and also following releases), then I prefer the practical option of spending valuable developer time & effort on things that will provide the best ROI.
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
1 reply
-
So the concern of maintaining a UWP test suite is to ensure bug fixes that pass .NET / Framework tests also work when running on .NET Native.
Right - it's about preventing regressions on UWP when we change or fix something on other platforms.
it takes time and effort to get everything done. Converting the test suite away from XUnit,
I've already done that—I have a branch on a repo in which I proved that it could be done. I wouldn't be suggesting it if it were an unknown. We aren't relying on xUnit-specific functionality. (In fact, years ago, all the tests were on MSTest anyway.) This is not a difficult change. It did not take me very long.
maintaining it for years, writing new tests against every new bug and feature
Well we are going to write tests for every new bug and feature in any case. Including those tests for UWP today is trivial compared to the effort of writing the tests, because they are literally the same code: the UWP test runner project uses file linking to compile in all the same files as the other test project. There are a handful that test UWP-specific behaviour, but those have already been written, and we don't intend to add any more UWP-specific behaviour. So there's no new effort here.
If we didn't have UWP support today it would take a non-trivial amount of work to get to the point where we do. But given that this work has already been done, the incremental increase in effort required to keep it that way is relatively small.
unless the community expresses a strong interest in UWP support
I don't think the absence of such expression would be a strong enough justification. If there is a lot of UWP usage, the community is unlikely to come and tell us that. We will simply get a backlash if we take UWP away. This is why I favour a three-phase approach instead of your suggestion two-phase approach. Phase 1 is that we do a minor update that continues to offer a UWP target (with the one difference being that in our plan, we continue to run the UWP test suite). Then for phase 2, I want to restructure the UWP support, with a view to flushing out people still using it so we can find out whether it's really being used or not, without actually dropping support. And then if it really turns out nobody cares, we will then have data to support that view, and we can remove UWP.
I should point out also that I speak as someone who has spent a significant chunk of the last month cursing the horrible state of UWP support in the .NET ecosystem as I've wrestled to get this project building on current tooling. I would absolutely love to drop UWP. I just don't feel it's reasonable yet. (Not least because I and a colleague have, independently, found ourselves needing to use UWP on two different projects in the last year despite really not wanting to. I fear it will live on longer than we might hope.)
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
0 replies
-
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
0 replies
{{actor}} deleted this content .
-
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
All reactions0 replies
-
If you have some time to tag any easy "first issues" that the community might be able to tackle that don't require in-depth knowledge of the code base right off the bat, I'd be happy to contribute whenever I have the time to.
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
1 reply
-
That would be great. I think we're planning to try and get all the modernisation tasks done, so that it's much simpler / less friction to get everything set up / tests running etc and then we'd absolutely love community contributions!
Beta Was this translation helpful? Give feedback.
-
It would be nice to see some long-standing PRs revisited and hopefully merged for v6.x. Especially #1545
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
1 reply
-
We will certainly be looking at that. One thing to consider, though, is that as @davidfowl suggested at #1868 (comment) we should also be considering whether the IAsyncEnumerable<T>
features currently in this repo should really be moved over to the dotnet/runtime repo.
Beta Was this translation helpful? Give feedback.
-
I would like to ask which method would be used to release Rx in unity platform?
Would it be nuget dll, or UPM package system, or anyway else?
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
3 replies
-
Currently, we deliver the package through NuGet. However, I'm not Unity expert, so if there are good reasons for us to consider alternatives, I'd be happy to look at that. This is the first time I've heard a suggestion that we need to use something other than NuGet. What do I need to know?
Beta Was this translation helpful? Give feedback.
-
As soon as you need to reference to unity specific things and are thus unable to publish your library onto NuGet to make it nicely usable to unity folks UPM is the way to go IMO.
I've noticed a few people on UPM using that approach however the whole dealing with NuGet in Unity is still a sort of niche (unless something mayor has happened in the last year). But ultimately with the whole to become more aligned with modern .Net I can't see Unity getting along without having a nicer way to use NuGet in the long term.
Beta Was this translation helpful? Give feedback.
{{actor}} deleted this content .
-
There are workaround to use nuget in unity, but it was not officially supported as of yet. Normally we would import raw source code or direct dll into unity
The ideal solution would be using UPM and release this library as git package. But if no maintainer ever familiar with unity then I would not request this approach. I could try include direct dll unpack from nuget if needed
On the other hand if there is raw source code package, it has ability to compile and directly in unity. So we can write platform or version specific preprocessor directive in there
ps. The most desirable way to use nuget in unity also require that it must be full version released of nuget, without any suffix like preview
Beta Was this translation helpful? Give feedback.
-
For those interested in Async Rx.NET see the following ADR: #1896
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
0 replies
{{actor}} deleted this content .
-
End of March 2023 Progress Update.@idg10 has been working hard this month, on Async Rx.NET, tackling more backlog items for Rx.NET v6 and triaging issues raised by the community.
📢 System.Reactive v6.0.0 Preview 9Available on NuGet: https://www.nuget.org/packages/System.Reactive/6.0.0-preview.9
Summary of changes:Full changelog: https://github.com/dotnet/reactive/releases/tag/rxnet-v6.0.0-preview.9
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
1 reply
-
I'm just going to provide some context on the xUnit -> MS Test change. (This is described elsewhere in ADRs, but anyone reading this progress update in isolation might find this change...surprising.) The basic issue is that xUnit's UWP support has been broken for several years. We don't expect them to fix that any time soon (or perhaps ever). But we need to verify that Rx works on UWP. This makes xUnit an unusable test platform for us. MS Test does provide full UWP support, so we've moved back to using that. (Rx used to use MS Test in the past.)
Beta Was this translation helpful? Give feedback.
-
Gain a consensus about reinstating some of the abstractions to better support downstream (cross) platform consumers (Avalonia / Uno / Unity / UWP / MAUI / Blazor / WPF / WinForms)
UniRx (https://github.com/neuecc/UniRx) is the Unity implementation of Reactive extensions with Unity utilities. In my opinion it is implemented well and has few bugs.
Supporting Unity means netstandard2.1 and avoiding nuget "batteries not included" dependencies, like the Microsoft logging and configuration namespace libraries.
Support between the two ecosystems' packaging is not tough, you can use https://openupm.com/nuget/
Also my opinion: the "zero allocation" emphasis in gaming libraries is more of a marketing issue. I would rather have a library that is high on correctness and implements all the operators and is tested, like Window, which UniRx currently lacks and is tricky for mortals like me to implement correctly.
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
2 replies
-
Also my opinion: the "zero allocation" emphasis in gaming libraries is more of a marketing issue
We at endjin have done a few projects involving zero-allocation or low-allocation code. Our experience is that it can make a phenomenal difference to performance in some scenarios. I don't know any Unity specifics, but based on my experience in other areas I would be wary of writing it off as marketing. (Also, many years ago, I used to work in real-time systems. There are soft real-time requirements associated with games that care about the perceived quality impact of maintaining consistent frame rates, and based on my own experiences with real-time development, it seems entirely plausible to me that zero allocation could be an important part of that.) However, I don't think it would be a realistic goal for System.Interactive
at this point.
At this stage I think it's an open question as to whether System.Reactive
could have anything to offer Unity—maybe they're happy with their own Rx. That said, we should definitely look at the reasons they give for being unable to use System.Reactive
(e.g., "issues with iOS IL2CPP compatibility") to see if we can do anything about those. Ideally, people should be able to use System.Reactive
in that world if they want to (e.g., to use operators that aren't implemented in UniRx).
Beta Was this translation helpful? Give feedback.
-
If the zero allocation thing is an issue or not depends on the specific use case and type of game.
Even without zero allocation I do see a benefit in offering those who don't need zero allocation with an alternative to UniRx.
Also I think it's worth pointing out that the way Garbage Collection works in unity has seen improvements in the last years and I it's entirely possible it won't provide as much frame drops anymore as it used to.
UniRx hasn't been maintained for years and it's still got some bugs that have been addressed in System.Reactive which is quite frustrating if you have to work around them.
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
0 replies
-
As a newcomer, the lack of a documentation site makes it still feel like this library is dead. The markdown in the documentation folder also looks unkept.
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
7 replies
-
I am a newbie. For me, rx gives me the feeling that it is tasteless to eat, a pity to discard, and the benefits are not high.
Beta Was this translation helpful? Give feedback.
{{actor}} deleted this content .
-
We're still working on this (kudos for finding the live url), and currently going through the first draft edit. There will be an announcement when we're happy with v1.
Beta Was this translation helpful? Give feedback.
-
Those following this discussion might be interested to know that we will soon be moving forward with the previous discussed plans for changing how UI-framework-specific features are packaged.
See #2177 for details.
Beta Was this translation helpful? Give feedback.
You must be logged in to vote
0 replies
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emojiYou can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4