diff --git a/README.md b/README.md index 6ddf1498..11eaf118 100644 --- a/README.md +++ b/README.md @@ -686,35 +686,23 @@ subject.Take(100).Count().Subscribe(x => Console.WriteLine(x)); Parallel.For(0, 1000, new ParallelOptions { MaxDegreeOfParallelism = 10 }, x => subject.OnNext(x)); ``` -This means that the issuance of OnNext must always be done on a single thread. Also, ReactiveProperty, which corresponds to BehaviorSubject in dotnet/reactive, is not thread-safe itself, so updating the value (set Value or call OnNext) must always be done on a single thread. - -For converting external inputs into Observables, such as with FromEvent, and when the source of input issues in a multi-threaded manner, it is necessary to synchronize using `Synchronize` to construct the correct operator chain. - -Of course, simply surrounding it with `lock` is also effective. +This means that the issuance of OnNext must always be done on a single thread. For converting external inputs into Observables, such as with `FromEvent`, and when the source of input issues in a multi-threaded manner, it is necessary to synchronize using `Synchronize` to construct the correct operator chain. ```csharp -lock(gate) -{ - subject.OnNext(value); -} +subject.Synchronoize(gate).Take(100).Count().Subscribe(); ``` -Unlike other Subjects, ReactiveProperty's OnNext/Subscribe operations are not thread-safe. Therefore, when using it in a multi-threaded environment, both operations need to be locked. +In R3, ReplaySubject and BehaviorSubject do not require Synchronize and are thread-safe, including OnNext. -```csharp -lock(gate) -{ - reactiveProperty.Value = value; -} +ReactiveProperty is not thread-safe and OnNext, set Value and Susbcribe cannot be called simultaneously. If you need to use it in such a situation, use `SynchronizedReactiveProperty` instead. -lock(gate) +```csharp +class MyClass { - reactiveProperty.Subscribe(observer); + public SynchronizedReactiveProperty Prop { get; } = new(); } ``` -Regarding Dispose of subscription, it is thread-safe. Additionally, if it's not possible to lock ReactiveProperty itself, you can use `SubscribeOnSynchronize` to apply a lock during Subscribe operations within the operator. - Sampling Timing --- The `Sample(TimeSpan)` in dotnet/reactive starts a timer in the background when subscribed to, and uses that interval for filtering. Additionally, the timer continues to run in the background indefinitely. diff --git a/sandbox/ConsoleApp1/Program.cs b/sandbox/ConsoleApp1/Program.cs index 05d2596f..ec43ff68 100644 --- a/sandbox/ConsoleApp1/Program.cs +++ b/sandbox/ConsoleApp1/Program.cs @@ -1,23 +1,10 @@ using R3; -using System.Diagnostics; -// https://github.com/Cysharp/R3/issues/232 +var r1 = Observable.Return(1); +var r2 = Observable.Interval(TimeSpan.FromSeconds(1)).Index(); +r1.Concat(r2).Subscribe(Console.WriteLine); -Observable.Concat( - Observable.Return("Start"), - SomeAsyncTask().ToObservable(), - Observable.Return("End") -).Subscribe(r => -{ - Console.WriteLine("Result:" + r); -}); +await Task.Delay(TimeSpan.FromDays(1)); // wait -Console.ReadLine(); - -async ValueTask SomeAsyncTask() -{ - await Task.Delay(1000); - return "result"; -}