Reactive Extensions
От: _NN_ www.nemerleweb.com
Дата: 22.11.19 11:37
Оценка: +1
Насколько актуально использование Reactive Extensions сегодня ?
Чем пользуетесь вы ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Reactive Extensions
От: Shmj Ниоткуда  
Дата: 22.11.19 17:40
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Насколько актуально использование Reactive Extensions сегодня ?

_NN>Чем пользуетесь вы ?

Как то использовал его в WinPhone 7 еще до того, как там появилась поддержка Task. Иначе там было сложно, вот тут описание: http://rsdn.org/forum/dotnet/4695296.all
Автор:
Дата: 10.04.12


Т.е. Rx заставила использовать кривая платформа. Думаю что из-за этой кривизны и усложнизма она и провалилась.

С тех пор никогда в жизни и намеков не было на задачи, где бы Rx был хоть сколько нибудь полезен. Если вы встречались на практике с такими задачами — хотелось бы услышать. Помоему абсолютно бесполезная хрень.
Отредактировано 22.11.2019 17:44 Shmj . Предыдущая версия .
Re: Reactive Extensions
От: Danchik Украина  
Дата: 22.11.19 18:47
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Насколько актуально использование Reactive Extensions сегодня ?

_NN>Чем пользуетесь вы ?

Немножко поигрался с этим, для чего хотите использовать?
Re[2]: Reactive Extensions
От: Shmj Ниоткуда  
Дата: 22.11.19 19:19
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Немножко поигрался с этим, для чего хотите использовать?


Вопрос как раз в том, кто и для чего использует. Зачем столько людей делают хрень, которая никому не нужна?
Re[2]: Reactive Extensions
От: _NN_ www.nemerleweb.com
Дата: 22.11.19 19:24
Оценка:
D>Немножко поигрался с этим, для чего хотите использовать?

Для работы, как для чего.
Пару лет назад использовал для удобной обработки данных.
С тех пор появились асинхронные потоки и остальные прелести во фреймворке.
Вот и вопрос есть ли ещё место для Rx в современном мире или что его заменяет.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Отписка
От: Qbit86 Кипр
Дата: 22.11.19 19:26
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Вопрос как раз в том, кто и для чего использует. Зачем столько людей делают хрень, которая никому не нужна?


Я не использую из-за специфики текущего окружения.
Но когда-то давно использовал в кровавом энтерпрайзе, просто как замену обычным .NET-ивентам. Это удобнее тем, что правильно организована отписка от события: при подписке возвращается IDisposable-токен. В то время как от обычных .NET-ивентов нельзя просто так взять и отписаться.
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: Reactive Extensions
От: _NN_ www.nemerleweb.com
Дата: 22.11.19 19:31
Оценка:
Здравствуйте, Shmj, Вы писали:

S>С тех пор никогда в жизни и намеков не было на задачи, где бы Rx был хоть сколько нибудь полезен. Если вы встречались на практике с такими задачами — хотелось бы услышать. Помоему абсолютно бесполезная хрень.


Каким образом решается передача данных асинхронно с фильтрами и обработчиками ?
Скажем в Rx легко написать что то вроде observable.Buffer(..).Scan(..).Throttle(..).Where(..)
https://gist.github.com/danielmoore/1182831

А как это делается сегодня без этой библиотеки ?
.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Reactive Extensions
От: Shmj Ниоткуда  
Дата: 22.11.19 20:25
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>А как это делается сегодня без этой библиотеки ?


Чем не устраивают Task/async/await?
Re[4]: Reactive Extensions
От: _NN_ www.nemerleweb.com
Дата: 23.11.19 03:32
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, _NN_, Вы писали:


_NN>>А как это делается сегодня без этой библиотеки ?


S>Чем не устраивают Task/async/await?


Устраивают конечно, но не всё легко выражается через одни async/await:

Например какие тут варианты реализации вместо Observable ?

var fsw = new FileSystemWatcher(@"C:\")
{ 
    IncludeSubdirectories = true,
    EnableRaisingEvents = true
};

var changes = from c in Observable.FromEventPattern<FileSystemEventArgs>(fsw, "Changed")
              select c.EventArgs.FullPath;

changes.Window(TimeSpan.FromSeconds(5)).Subscribe(async window =>
{
    var count = await window.Count();
    Console.WriteLine("{0} events last 5 seconds", count);
});
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Reactive Extensions
От: okon  
Дата: 24.11.19 06:46
Оценка:
S>С тех пор никогда в жизни и намеков не было на задачи, где бы Rx был хоть сколько нибудь полезен. Если вы встречались на практике с такими задачами — хотелось бы услышать. Помоему абсолютно бесполезная хрень.

Очень простая задача встречающаяся практически в любом интерфейсе — нужно отобразить список Items[] GetList(string filter) который формируется долго, задержка плавающая т.е. может от 0.1 секунды ответ прийти до 5 секунд, пользователь вводит данные в поле filter, запрос сразу отправлять не требуется, только после 500 миллисекунд после того как пользователь перестал вводить данные. Нужно отображать актуальный список в UI соотвествующий последнему введеному filter.

Теперь напиши решение этой задачи на async/await.


Потом немного усложним условие — есть еще Checkbox который также отвечает за алгоритм фильтрации ( например Ignore Case в фильтре ).

Доработай решение на async/await чтобы также учитывать изменение Checkbox ( по той же логике что и изменение строки 500 мс игнорим событие потом продолжаем если пользователь ничего не менят ).
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Re[3]: Reactive Extensions
От: Shmj Ниоткуда  
Дата: 24.11.19 13:50
Оценка:
Здравствуйте, okon, Вы писали:

O>Очень простая задача встречающаяся практически в любом интерфейсе — нужно отобразить список Items[] GetList(string filter) который формируется долго, задержка плавающая т.е. может от 0.1 секунды ответ прийти до 5 секунд, пользователь вводит данные в поле filter, запрос сразу отправлять не требуется, только после 500 миллисекунд после того как пользователь перестал вводить данные. Нужно отображать актуальный список в UI соотвествующий последнему введеному filter.


Примерно так (набросал идею), обновленная версия: http://rsdn.org/forum/dotnet/7596599.1
Автор: Shmj
Дата: 24.11.19
Отредактировано 24.11.2019 17:01 Shmj . Предыдущая версия .
Re[4]: Reactive Extensions
От: Somescout  
Дата: 24.11.19 14:13
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, okon, Вы писали:


O>>Очень простая задача встречающаяся практически в любом интерфейсе — нужно отобразить список Items[] GetList(string filter) который формируется долго, задержка плавающая т.е. может от 0.1 секунды ответ прийти до 5 секунд, пользователь вводит данные в поле filter, запрос сразу отправлять не требуется, только после 500 миллисекунд после того как пользователь перестал вводить данные. Нужно отображать актуальный список в UI соотвествующий последнему введеному filter.


S>Примерно так (набросал идею):


S>
S>        private volatile bool _changed;

S>        private void textBox1_KeyUp(object sender, KeyEventArgs e)
S>        {
S>            _changed = true;
S>            FillItems();
S>        }

S>        private async void FillItems()
S>        {
S>            _changed = false;
S>            await Task.Delay(500);

S>            if (_changed)
S>                return;

S>            textBox2.Clear();

S>            var items = await MakeRequest(textBox1.Text);

S>            if (_changed)
S>                return;

S>            textBox2.Text = string.Join("\r\n", items);
S>        }

S>        Random _random = new Random();
S>        private async Task<List<string>> MakeRequest(string q)
S>        {
S>            await Task.Delay(_random.Next(100, 5000));
S>            return await Task.FromResult(new List<string>()
S>            {
S>                q + "пункт 1 ",
S>                q + "пункт 2",
S>                q + "пункт 3",
S>            });
S>        }
S>


Тут уже в алгоритме ошибка: таймер ожидания должен сбрасываться после каждого нажатия клавиши, а у вас после первого нажатия через 500 мс запрос уйдёт в любом случае. Более того, я могу ошибаться, но запрос будет отправлен по всем нажатиям клавиш, потому что не делается проверка что асинхронная функция уже была вызвана.
ARI ARI ARI... Arrivederci!
Re[5]: Reactive Extensions
От: Shmj Ниоткуда  
Дата: 24.11.19 14:56
Оценка:
Здравствуйте, Somescout, Вы писали:

S>Тут уже в алгоритме ошибка: таймер ожидания должен сбрасываться после каждого нажатия клавиши, а у вас после первого нажатия через 500 мс запрос уйдёт в любом случае.


Нет, т.к. после 500 мс ожидания идет проверка. Если была нажата клавиша — будет установлен флаг _changed и выход из функции.

if (_changed)
   return;


S>Более того, я могу ошибаться, но запрос будет отправлен по всем нажатиям клавиш, потому что не делается проверка что асинхронная функция уже была вызвана.


Да, по тем что успели отправить — уже не отменяем.

Чтобы не гадать — запустите, это WinForms-приложение. 2 TextBox кинуть на форму и у первого TextBox подписка на textBox1_KeyUp.
Отредактировано 24.11.2019 15:02 Shmj . Предыдущая версия . Еще …
Отредактировано 24.11.2019 14:57 Shmj . Предыдущая версия .
Re[6]: Reactive Extensions
От: Somescout  
Дата: 24.11.19 14:57
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, Somescout, Вы писали:


S>>>Примерно так (набросал идею):


S>>>
S>>>        private volatile bool _changed;

S>>>        private void textBox1_KeyUp(object sender, KeyEventArgs e)
S>>>        {
S>>>            _changed = true;
S>>>            FillItems();
S>>>        }

S>>>        private async void FillItems()
S>>>        {
S>>>            _changed = false;
S>>>            await Task.Delay(500);

S>>>            if (_changed)
S>>>                return;

S>>>            textBox2.Clear();

S>>>            var items = await MakeRequest(textBox1.Text);

S>>>            if (_changed)
S>>>                return;

S>>>            textBox2.Text = string.Join("\r\n", items);
S>>>        }

S>>>        Random _random = new Random();
S>>>        private async Task<List<string>> MakeRequest(string q)
S>>>        {
S>>>            await Task.Delay(_random.Next(100, 5000));
S>>>            return await Task.FromResult(new List<string>()
S>>>            {
S>>>                q + "пункт 1 ",
S>>>                q + "пункт 2",
S>>>                q + "пункт 3",
S>>>            });
S>>>        }
S>>>


S>>Тут уже в алгоритме ошибка: таймер ожидания должен сбрасываться после каждого нажатия клавиши, а у вас после первого нажатия через 500 мс запрос уйдёт в любом случае.


S>Нет, т.к. после 500 мс ожидания идет проверка. Если была нажата клавиша — будет установлен флаг _changed и выход из функции.


У вас после нажатия на клавишу сразу без ожидания будет вызвана функция FillItems, которая сразу же сбросит этот флаг.

S>>Более того, я могу ошибаться, но запрос будет отправлен по всем нажатиям клавиш, потому что не делается проверка что асинхронная функция уже была вызвана.


S>См. выше.


См. выше
ARI ARI ARI... Arrivederci!
Re[7]: Reactive Extensions
От: Shmj Ниоткуда  
Дата: 24.11.19 15:16
Оценка:
Здравствуйте, Somescout, Вы писали:

S>У вас после нажатия на клавишу сразу без ожидания будет вызвана функция FillItems, которая сразу же сбросит этот флаг.


Ваша правда. Без счетчика запросов не обойтись:

        private volatile int _lastRequestId;

        private void textBox1_KeyUp(object sender, KeyEventArgs e)
        {
            _lastRequestId++;
            FillItems();
        }

        private async void FillItems()
        {
            var requestId = _lastRequestId;

            await Task.Delay(500);

            if (requestId != _lastRequestId)
                return;

            textBox2.Clear();

            var items = await MakeRequest(textBox1.Text);

            if (_lastRequestId != requestId)
                return;

            textBox2.Text = string.Join("\r\n", items);
        }

        Random _random = new Random();
        private async Task<List<string>> MakeRequest(string q)
        {
            await Task.Delay(_random.Next(100, 5000));
            return await Task.FromResult(new List<string>()
            {
                q + " пункт 1 ",
                q + " пункт 2",
                q + " пункт 3",
            });
        }


Еще вариант с отменой:

        private void textBox1_KeyUp(object sender, KeyEventArgs e)
        {
            FillItems();
        }

        private CancellationTokenSource _cancelTokenSource;

        private async void FillItems()
        {
            _cancelTokenSource?.Cancel(true);

            var cancelTokenSource = new CancellationTokenSource();

            _cancelTokenSource = cancelTokenSource;

            try
            {
                await Task.Delay(500, cancelTokenSource.Token);
                textBox2.Clear();

                var items = await MakeRequest(textBox1.Text, cancelTokenSource.Token);
                textBox2.Text = string.Join("\r\n", items);
            }
            catch (TaskCanceledException)
            {
            }
        }

        Random _random = new Random();
        private async Task<List<string>> MakeRequest(string q, CancellationToken cancellationToken)
        {
            await Task.Delay(_random.Next(100, 5000), cancellationToken);

            Console.Beep(1000, 10);

            return await Task.FromResult(new List<string>()
            {
                q + " пункт 1 ",
                q + " пункт 2",
                q + " пункт 3",
            });
        }


Теперь ваш вариант на Reactive Extensions.
Отредактировано 24.11.2019 18:03 Shmj . Предыдущая версия . Еще …
Отредактировано 24.11.2019 16:07 Shmj . Предыдущая версия .
Re[4]: Reactive Extensions
От: okon  
Дата: 24.11.19 16:53
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, okon, Вы писали:


O>>Очень простая задача встречающаяся практически в любом интерфейсе — нужно отобразить список Items[] GetList(string filter) который формируется долго, задержка плавающая т.е. может от 0.1 секунды ответ прийти до 5 секунд, пользователь вводит данные в поле filter, запрос сразу отправлять не требуется, только после 500 миллисекунд после того как пользователь перестал вводить данные. Нужно отображать актуальный список в UI соотвествующий последнему введеному filter.


S>, 5000));

S> return await Task.FromResult(new List<string>()
S> {
S> q + "пункт 1 ",
S> q + "пункт 2",
S> q + "пункт 3",
S> }


Только стандартный баг ты сделал в таком решении, то что если предыдущий запрос будет дольше чем новый то старый запрос перетрет данные и они будут не релевантны фильтру
Поиграйся с этим решением, заметишь баг.

O>>Потом немного усложним условие — есть еще Checkbox который также отвечает за алгоритм фильтрации ( например Ignore Case в фильтре ).


S>И чем это усложнит?


Да тут нужнл еще условие что с чек боксом должен другой метод "сервиса" вызываться.
Попробуй.


Потом посмотри как просто и элегантно подобная задача решается в парадигме RX.
Она обычно есть в разных примерах.одна строка.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Re[5]: Reactive Extensions
От: Shmj Ниоткуда  
Дата: 24.11.19 17:01
Оценка:
Здравствуйте, okon, Вы писали:

O>Только стандартный баг ты сделал в таком решении, то что если предыдущий запрос будет дольше чем новый то старый запрос перетрет данные и они будут не релевантны фильтру

O>Поиграйся с этим решением, заметишь баг.

Вот тут исправлено: http://rsdn.org/forum/dotnet/7596599.1
Автор: Shmj
Дата: 24.11.19
Re[5]: Reactive Extensions
От: Shmj Ниоткуда  
Дата: 24.11.19 17:51
Оценка:
Здравствуйте, okon, Вы писали:

O>Потом посмотри как просто и элегантно подобная задача решается в парадигме RX.

O>Она обычно есть в разных примерах.одна строка.

Я привел пример
Автор: Shmj
Дата: 24.11.19
на Task. Жду от вас на Rx. Давайте сравнивать...
Отредактировано 24.11.2019 17:51 Shmj . Предыдущая версия .
Re[6]: Reactive Extensions
От: okon  
Дата: 24.11.19 18:27
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, okon, Вы писали:


O>>Потом посмотри как просто и элегантно подобная задача решается в парадигме RX.

O>>Она обычно есть в разных примерах.одна строка.

S>Я привел пример
Автор: Shmj
Дата: 24.11.19
на Task. Жду от вас на Rx. Давайте сравнивать...


inputObservable
      .Throttle(500)
      .CombineLatest(input => GetList(input))
      .OnNext( result => texbBox.text = result );


Ну и по событию кидать в inputObservable новые данные
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Re[7]: Reactive Extensions
От: Shmj Ниоткуда  
Дата: 24.11.19 18:38
Оценка:
Здравствуйте, okon, Вы писали:

O>
O>inputObservable
O>      .Throttle(500)
O>      .CombineLatest(input => GetList(input))
O>      .OnNext( result => texbBox.text = result );
O>


O>Ну и по событию кидать в inputObservable новые данные


Давайте весь код, чтобы сразу запустить. Я дал весь, на форму только кинуть 2 TextBox.

И добавьте textBox2.Clear(); после задержки в 500 мс.
Отредактировано 24.11.2019 18:52 Shmj . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.