Здравствуйте, _NN_, Вы писали:
_NN>Насколько актуально использование Reactive Extensions сегодня ? _NN>Чем пользуетесь вы ?
Как то использовал его в WinPhone 7 еще до того, как там появилась поддержка Task. Иначе там было сложно, вот тут описание: http://rsdn.org/forum/dotnet/4695296.all
Т.е. Rx заставила использовать кривая платформа. Думаю что из-за этой кривизны и усложнизма она и провалилась.
С тех пор никогда в жизни и намеков не было на задачи, где бы Rx был хоть сколько нибудь полезен. Если вы встречались на практике с такими задачами — хотелось бы услышать. Помоему абсолютно бесполезная хрень.
D>Немножко поигрался с этим, для чего хотите использовать?
Для работы, как для чего.
Пару лет назад использовал для удобной обработки данных.
С тех пор появились асинхронные потоки и остальные прелести во фреймворке.
Вот и вопрос есть ли ещё место для Rx в современном мире или что его заменяет.
Здравствуйте, Shmj, Вы писали:
S>Вопрос как раз в том, кто и для чего использует. Зачем столько людей делают хрень, которая никому не нужна?
Я не использую из-за специфики текущего окружения.
Но когда-то давно использовал в кровавом энтерпрайзе, просто как замену обычным .NET-ивентам. Это удобнее тем, что правильно организована отписка от события: при подписке возвращается IDisposable-токен. В то время как от обычных .NET-ивентов нельзя просто так взять и отписаться.
Здравствуйте, Shmj, Вы писали:
S>С тех пор никогда в жизни и намеков не было на задачи, где бы Rx был хоть сколько нибудь полезен. Если вы встречались на практике с такими задачами — хотелось бы услышать. Помоему абсолютно бесполезная хрень.
Каким образом решается передача данных асинхронно с фильтрами и обработчиками ?
Скажем в Rx легко написать что то вроде observable.Buffer(..).Scan(..).Throttle(..).Where(..) https://gist.github.com/danielmoore/1182831
А как это делается сегодня без этой библиотеки ?
.
Здравствуйте, 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);
});
S>С тех пор никогда в жизни и намеков не было на задачи, где бы Rx был хоть сколько нибудь полезен. Если вы встречались на практике с такими задачами — хотелось бы услышать. Помоему абсолютно бесполезная хрень.
Очень простая задача встречающаяся практически в любом интерфейсе — нужно отобразить список Items[] GetList(string filter) который формируется долго, задержка плавающая т.е. может от 0.1 секунды ответ прийти до 5 секунд, пользователь вводит данные в поле filter, запрос сразу отправлять не требуется, только после 500 миллисекунд после того как пользователь перестал вводить данные. Нужно отображать актуальный список в UI соотвествующий последнему введеному filter.
Теперь напиши решение этой задачи на async/await.
Потом немного усложним условие — есть еще Checkbox который также отвечает за алгоритм фильтрации ( например Ignore Case в фильтре ).
Доработай решение на async/await чтобы также учитывать изменение Checkbox ( по той же логике что и изменение строки 500 мс игнорим событие потом продолжаем если пользователь ничего не менят ).
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Здравствуйте, okon, Вы писали:
O>Очень простая задача встречающаяся практически в любом интерфейсе — нужно отобразить список Items[] GetList(string filter) который формируется долго, задержка плавающая т.е. может от 0.1 секунды ответ прийти до 5 секунд, пользователь вводит данные в поле filter, запрос сразу отправлять не требуется, только после 500 миллисекунд после того как пользователь перестал вводить данные. Нужно отображать актуальный список в UI соотвествующий последнему введеному filter.
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, okon, Вы писали:
O>>Очень простая задача встречающаяся практически в любом интерфейсе — нужно отобразить список Items[] GetList(string filter) который формируется долго, задержка плавающая т.е. может от 0.1 секунды ответ прийти до 5 секунд, пользователь вводит данные в поле filter, запрос сразу отправлять не требуется, только после 500 миллисекунд после того как пользователь перестал вводить данные. Нужно отображать актуальный список в UI соотвествующий последнему введеному filter.
S>Примерно так (набросал идею):
S>
Тут уже в алгоритме ошибка: таймер ожидания должен сбрасываться после каждого нажатия клавиши, а у вас после первого нажатия через 500 мс запрос уйдёт в любом случае. Более того, я могу ошибаться, но запрос будет отправлен по всем нажатиям клавиш, потому что не делается проверка что асинхронная функция уже была вызвана.
Здравствуйте, Somescout, Вы писали:
S>Тут уже в алгоритме ошибка: таймер ожидания должен сбрасываться после каждого нажатия клавиши, а у вас после первого нажатия через 500 мс запрос уйдёт в любом случае.
Нет, т.к. после 500 мс ожидания идет проверка. Если была нажата клавиша — будет установлен флаг _changed и выход из функции.
if (_changed)
return;
S>Более того, я могу ошибаться, но запрос будет отправлен по всем нажатиям клавиш, потому что не делается проверка что асинхронная функция уже была вызвана.
Да, по тем что успели отправить — уже не отменяем.
Чтобы не гадать — запустите, это WinForms-приложение. 2 TextBox кинуть на форму и у первого TextBox подписка на textBox1_KeyUp.
S>>Тут уже в алгоритме ошибка: таймер ожидания должен сбрасываться после каждого нажатия клавиши, а у вас после первого нажатия через 500 мс запрос уйдёт в любом случае.
S>Нет, т.к. после 500 мс ожидания идет проверка. Если была нажата клавиша — будет установлен флаг _changed и выход из функции.
У вас после нажатия на клавишу сразу без ожидания будет вызвана функция FillItems, которая сразу же сбросит этот флаг.
S>>Более того, я могу ошибаться, но запрос будет отправлен по всем нажатиям клавиш, потому что не делается проверка что асинхронная функция уже была вызвана.
S>См. выше.
Здравствуйте, 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",
});
}
Здравствуйте, 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.
Она обычно есть в разных примерах.одна строка.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Здравствуйте, okon, Вы писали:
O>Только стандартный баг ты сделал в таком решении, то что если предыдущий запрос будет дольше чем новый то старый запрос перетрет данные и они будут не релевантны фильтру O>Поиграйся с этим решением, заметишь баг.
Здравствуйте, okon, Вы писали:
O>Потом посмотри как просто и элегантно подобная задача решается в парадигме RX. O>Она обычно есть в разных примерах.одна строка.
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, okon, Вы писали:
O>>Потом посмотри как просто и элегантно подобная задача решается в парадигме RX. O>>Она обычно есть в разных примерах.одна строка.
S>Я привел пример
inputObservable
.Throttle(500)
.CombineLatest(input => GetList(input))
.OnNext( result => texbBox.text = result );
Ну и по событию кидать в inputObservable новые данные
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
S>Давайте весь код, чтобы сразу запустить. Я дал весь, на форму только кинуть 2 TextBox.
Давайте тогда ваш пример на GitHub, чтобы и ваш запустить, туда и код с Rx можно добавить будет для сравнения
Здравствуйте, _NN_, Вы писали:
S>>Давайте весь код, чтобы сразу запустить. Я дал весь, на форму только кинуть 2 TextBox. _NN>Давайте тогда ваш пример на GitHub, чтобы и ваш запустить, туда и код с Rx можно добавить будет для сравнения
А что на Rx получается такой большой код, что нужен GitHub?
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, okon, Вы писали:
O>>
O>>inputObservable
O>> .Throttle(500)
O>> .CombineLatest(input => GetList(input))
O>> .OnNext( result => texbBox.text = result );
O>>
O>>Ну и по событию кидать в inputObservable новые данные
S>Давайте весь код, чтобы сразу запустить. Я дал весь, на форму только кинуть 2 TextBox.
S>И добавьте textBox2.Clear(); после задержки в 500 мс.
Сори, но мне лично лень делать под тебя отдельный проект и проверять компиляцию.
Я показал как выглядит решение на Rx, если тебя прям весь код интересует то могу написать примерно с точностью до типов, а дальше сам ковыряй.
Те количество строк не должно измениться в решении , это все решение :
Observable<string[]> inputObservable = new Observable<string[]>();
// любое место где инициализация формыvoid Init()
{
inputObservable
.Throttle(500)
.CombineLatest(input => GetList(input))
.Subscribe( result => texbBox.text = result );
}
void KeyDown(EventArgs e) => inputObservable.OnNext(e);
Вот это твой эквивалент этой же логики
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);
}
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, _NN_, Вы писали:
S>>>Давайте весь код, чтобы сразу запустить. Я дал весь, на форму только кинуть 2 TextBox. _NN>>Давайте тогда ваш пример на GitHub, чтобы и ваш запустить, туда и код с Rx можно добавить будет для сравнения
S>А что на Rx получается такой большой код, что нужен GitHub?
Чтобы избежать недопониманий.
Я точно также не могу взять ваш код и скомпилировать, нужен код всего проекта.
Здравствуйте, _NN_, Вы писали:
_NN>Я точно также не могу взять ваш код и скомпилировать, нужен код всего проекта.
так код с Rx не воспроизводит всех возможностей первого кода...потому просто не конкурент и 1-е решение лучше и гибче.
в частности если послан запрос, 500 мс прошло, еще ввод, ответ (5сек) еще не пришел ... пошлетcя еще запрос не дождавшись предыдущего ответа?
Здравствуйте, paradoks, Вы писали:
P>Здравствуйте, _NN_, Вы писали:
_NN>>Я точно также не могу взять ваш код и скомпилировать, нужен код всего проекта.
P>так код с Rx не воспроизводит всех возможностей первого кода...потому просто не конкурент и 1-е решение лучше и гибче.
Почему ? Как раз воспроизводит без лишнего кода.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Здравствуйте, okon, Вы писали:
O>Здравствуйте, paradoks, Вы писали:
P>>Здравствуйте, _NN_, Вы писали:
_NN>>>Я точно также не могу взять ваш код и скомпилировать, нужен код всего проекта.
P>>так код с Rx не воспроизводит всех возможностей первого кода...потому просто не конкурент и 1-е решение лучше и гибче.
O>Почему ? Как раз воспроизводит без лишнего кода.
O>>Почему ? Как раз воспроизводит без лишнего кода.
P>а где второй таймаут на 5 сек?
А что за таймаут на 5 сек ?
Покажи часть кода и выдели где это.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, okon, Вы писали:
O>>Вот это твой эквивалент этой же логики
S>А где:
S>
S>textBox2.Clear();
S>
S>?
Добавь строчку
...
.Throttle(500)
.Subscribe( input => textBox2.Clear() )
.CombineLatest( input => GetList(input))
.Subscribe( result => textBox2.text = result );
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
O>>>Почему ? Как раз воспроизводит без лишнего кода.
P>>а где второй таймаут на 5 сек?
O>А что за таймаут на 5 сек ?
O>Покажи часть кода и выдели где это.
врем ожидания ответа 0.1 — 5 сек
значит поле 5 сек надо что-то сделать. убить запрос и тд.
Здравствуйте, paradoks, Вы писали:
P>Здравствуйте, okon, Вы писали:
O>>>>Почему ? Как раз воспроизводит без лишнего кода.
P>>>а где второй таймаут на 5 сек?
O>>А что за таймаут на 5 сек ?
O>>Покажи часть кода и выдели где это.
P>врем ожидания ответа 0.1 — 5 сек P>значит поле 5 сек надо что-то сделать. убить запрос и тд.
А где в решении без Rx убивается запрос и т.д. ? не вижу.
В Rx там достаточно просто делается , добавляется .Timeout(TimeSpan.FromMilliseconds(1000))
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, okon, Вы писали:
O>>
O>> Observable<string[]> inputObservable = new Observable<string[]>();
O>> // любое место где инициализация формы
O>> void Init()
O>> {
O>> inputObservable
O>> .Throttle(500)
O>> .CombineLatest(input => GetList(input))
O>> .Subscribe( result => texbBox.text = result );
O>> }
O>> void KeyDown(EventArgs e) => inputObservable.OnNext(e);
O>>
O>>Вот это твой эквивалент этой же логики
S>А теперь вопрос: с чего вы взяли, что ваш код проще? Лишь потому что он записан в одну очень очень длинную строку?
Намного проще, точнее логику описываешь в одном месте, а не балуешься с флажками и сложными условиями.
Сложность здесь в том что надо перевернуть мозги. Например всех тонкостей я так и не познал.
Из минусов что я нашел — если где-то в звене, какой-то подписчик бросит исключение, то вся цепь отвалится.
Здравствуйте, Danchik, Вы писали:
D>Намного проще, точнее логику описываешь в одном месте, а не балуешься с флажками и сложными условиями.
Нет, не проще. Давайте полный код, мне лень писать, т.к. мысль об Observable вызывает у меня боль.
Для Task-ов я написал.
D>Сложность здесь в том что надо перевернуть мозги. Например всех тонкостей я так и не познал.
Обман. Я работал с ними в 2012 году где-то месяца 3 довольно плотно и познал все тонкости. Но потом, когда необходимость такая отпала — вздохнул с облегчением и почти все забыл, вспоминать желания не возникает.
D>Из минусов что я нашел — если где-то в звене, какой-то подписчик бросит исключение, то вся цепь отвалится.
Там много минусов по этому никто не осмеливается привести полный код. Вот тот что привели:
Observable<string[]> inputObservable = new Observable<string[]>();
Здравствуйте, Danchik, Вы писали:
D>Не претендую на супер знание Rx. Но родил такое: D>Заумно как на меня, разве что каждый день такое рожать.
Ага. Запустите анализатор кода VS — и получите, что с Rx 55 строк кода против 43 с Tasks. Т.е. строк кода получилось больше.
В чем же обещанная простота?
Многое не очевидно. Вот эта строчка, к примеру, зачем нужна:
.ObserveOn(textBox2)
Без нее все работает. Типа метод Invoke вызывает?
Короче говоря, эта штука для тех, у кого низкая самооценка и кто хочет как-то укрепиться за счет того, что типа использует что-то диковинное, что якобы не каждому под силу. На самом деле особо сложнго ничего нет — просто не удобно.
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, Danchik, Вы писали:
D>>Не претендую на супер знание Rx. Но родил такое: D>>Заумно как на меня, разве что каждый день такое рожать.
S>Ага. Запустите анализатор кода VS — и получите, что с Rx 55 строк кода против 43 с Tasks. Т.е. строк кода получилось больше.
S>В чем же обещанная простота?
Вы простоту а количествах строк меняете ?
По этой логике Go супер сложный язык .
S>Многое не очевидно. Вот эта строчка, к примеру, зачем нужна:
S>
S>.ObserveOn(textBox2)
S>
Чтобы контекст вызова был на UI потоке
Когда нужно обрабаьваать реактивный поток данных удобно, что есть LINQ методы, и можно описать код декларативно.
Скажем, в вашем примере есть ещё счётчик ,который по хорошему следует инкапсулировать во вспомогательный класс, иначе логика обработки и обвязка размазываются .
Здравствуйте, Ночной Смотрящий, Вы писали:
S>>А теперь вопрос: с чего вы взяли, что ваш код проще? Лишь потому что он записан в одну очень очень длинную строку? НС>Нет. Прежде всего потому что описывает что сделать, а не как сделать.
Нет, это так не работает. Легкость не определяется формальными параметрами.
Я же вам говорю — в 2012 я плотно работал с Rx, познал почти все тонкости. Вынужденно. Но вспоминаю это время с болью и повторять не хочется.
Здравствуйте, _NN_, Вы писали:
S>>В чем же обещанная простота? _NN>Вы простоту а количествах строк меняете ? _NN>По этой логике Go супер сложный язык .
Количество строк/символов — один из показателей. Чем больше придетя писать — тем более лениво.
Формальный подход — типа декларация всегда лучше императивности — не всегда работает. Иногда императивность проще.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>>Нет. Прежде всего потому что описывает что сделать, а не как сделать. S>>Нет, это так не работает. НС>Это именно так и работает.
Далеко не так. Есть такие паршивые способы конфигурирования и декларирования, что императивность во много раз проще и удобнее.
S>>Я же вам говорю — в 2012 я плотно работал с Rx, познал почти все тонкости. НС>Незаметно.