1

I have this code from old examples (Reactive UI 4):

StartAsyncCommand = new ReactiveCommand();
        StartAsyncCommand.RegisterAsyncAction(_ =>
        {
            Progress = 0;
            var exe = Enumerable.Range(0, 10).Select(x =>
                            {
                                Thread.Sleep(100);
                                return x;
                            }).ToObservable();
            exe.Subscribe(x =>Progress += 10);
        });

It works fine, UI does not block and button is disable until Progress gets 100%.

When I migrate to version 6, I tried many ways to achieve same functionality without success.

These are my attempts:

1) Using CreateAsyncObservable

GenerateCommand = ReactiveCommand.CreateAsyncObservable(canGenerate, x => DoSomething());

public IObservable<Unit> DoSomething()
    {
        var exe = Enumerable.Range(0, 10).Select(
            x =>
            {
                Thread.Sleep(200);
                return x;
            }).ToObservable().ObserveOnDispatcher().SubscribeOn(NewThreadScheduler.Default);
        exe.Subscribe(x =>
                Progress += 10
            );
        return Observable.Return(new Unit());
    }

It works but button does not disable.

2) With CreateAsyncTask

GenerateCommand = ReactiveCommand.CreateAsyncTask(canGenerate, x => DoSomething());

public async Task<Unit> DoSomething()
    {
        var exe = Enumerable.Range(0, 10).Select(
            x =>
            {
                Thread.Sleep(200);
                return x;
            }).ToObservable().ObserveOnDispatcher().SubscribeOn(NewThreadScheduler.Default);
                    await exe;
        exe.Subscribe(x =>
                                Progress+=10

            );
        return new Unit();
    }

It works but button only disable until await ends.

3) Based on ReactiveUI 6 Async Command Not Running on Background Thread in WPF app

GenerateCommand = ReactiveCommand.CreateAsyncTask(canGenerate, x => DoSomething());

public async Task<Unit> DoSomething()
{
        var execTask = Task.Factory.StartNew(() =>
        {
            var exe = Enumerable.Range(0, 10).Select(
                            x =>
                            {
                                Thread.Sleep(200);
                                return x;
                            }).ToObservable();
            exe.Subscribe(x =>
                    Progress += 10
                );
            return new Unit();
        });

        return execTask.Result; 
 }

This throws an exception.

UPDATE

4) Subscribe command:

GenerateCommand = ReactiveCommand.CreateAsyncObservable(canGenerate, x => DoSomething());
GenerateCommand.ObserveOnDispatcher().SubscribeOn(NewThreadScheduler.Default)
    .Subscribe(x => Progress += 10);

    public IObservable<int> DoSomething()
    {
        return = Observable.Range(0, 10).Select(
            x =>
            {
                Thread.Sleep(200);
                return x;
            });
    }

Same result...

How could I achieve same functionality with version 6?

What am I doing wrong?

Community
  • 1
  • 1
UUHHIVS
  • 1,179
  • 11
  • 19
  • Why are you doing `Enumerable.Range(...).ToObservable` instead of `Observable.Range(...)`? You should always avoid going from `Enumerable` to `Observable` where possible. – Enigmativity Oct 18 '14 at 04:40
  • Why also are you subscribing to an observable inside a task? It seems like you don't understand how to use Rx properly. – Enigmativity Oct 18 '14 at 04:41
  • 1
    Thank you for your suggestion, but the question is how achieve same functionality... As I said I tried several codes... I updated question with other code that I also tried... I hope you could help me with an example! – UUHHIVS Oct 18 '14 at 05:41
  • I wasn't answering the question - I was merely commenting on your code. My feeling is that your troubles stem from the way you are mixing TPL, Rx & Linq (Enumerables). – Enigmativity Oct 18 '14 at 06:58

1 Answers1

5

This is a very odd way to do what you're trying to do. How about this instead:

StartAsyncCommand = ReactiveCommand.CreateAsyncObservable(_ => 
    Observable.Timer(DateTimeOffset.Zero, TimeSpan.FromSeconds(1))
        .Take(10)
        .Scan(0, (acc,x) => acc + 10));

StartAsyncCommand.ToProperty(this, x => x.Progress, out progress);
Ana Betts
  • 73,868
  • 16
  • 141
  • 209