Здравствуйте, Serginio1, Вы писали:
SS>>Хочется иметь SynchronizationContext SS>>- который бы сериализовал колбэки, так что только один колбэк испольняется в момент времени SS>>- не являлся бю UI-ным SynchronizationContext-ом, а испльзовал бы тред пул. Никакой тред не должен спать, ожидая колбэков.
SS>>Нужно для IO-bound фоновый задачи, которая запускает параллельные составные IO таски и не хочет синзронизировать доступ к общим переменным между await-ами.
S> Может я не понял вопроса, но вот здесь Consuming the Task-based Asynchronous Pattern
Не проще было ConcurrentExclusiveSchedulerPair использовать?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, TK, Вы писали:
TK>Здравствуйте, Serginio1, Вы писали:
SS>>>Хочется иметь SynchronizationContext SS>>>- который бы сериализовал колбэки, так что только один колбэк испольняется в момент времени SS>>>- не являлся бю UI-ным SynchronizationContext-ом, а испльзовал бы тред пул. Никакой тред не должен спать, ожидая колбэков.
SS>>>Нужно для IO-bound фоновый задачи, которая запускает параллельные составные IO таски и не хочет синзронизировать доступ к общим переменным между await-ами.
S>> Может я не понял вопроса, но вот здесь Consuming the Task-based Asynchronous Pattern
TK>Не проще было ConcurrentExclusiveSchedulerPair использовать?
Спасибо Тимофей! Буду мотать на ус. Просто подумалось, что ему хватит асинхронной очереди BufferBlock, для последовательного выполнения калбеков.
Но так как я мало пишу на C£, то видно многое упускаю. Буду разбираться.
и солнце б утром не вставало, когда бы не было меня
Наверное, то что предлагают Sinix и ТК более подходит для решения твоей задачи.
Тебе же не обязательно, что бы выполнялось в одном потоке? Главное, что бы последовательно?
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, SuhanovSergey, Вы писали:
SS>Хочется иметь SynchronizationContext SS>- который бы сериализовал колбэки, так что только один колбэк испольняется в момент времени SS>- не являлся бю UI-ным SynchronizationContext-ом, а испльзовал бы тред пул. Никакой тред не должен спать, ожидая колбэков.
SS>Нужно для IO-bound фоновый задачи, которая запускает параллельные составные IO таски и не хочет синзронизировать доступ к общим переменным между await-ами.
Здравствуйте, Sinix, Вы писали: S>Здравствуйте, Serginio1, Вы писали: S>> Там пример на ConfigureAwait(false) для библиотек для того, что бы они не вызываличь в потоке UI. S>Эта ошибка с любым лимитированным шедулером возможна, просто понадобится больше ожидающих задач. S>Лечить надо причину, а не симптомы. S>>Лучше бы сделали наоборот, сто по умолчанию ConfigureAwait(false) S>Как обычно: предлагаем что-то — не останавливаемся,а думаем "а что, если моё пожелание сбудется?". Дальше продолжать?
S>>Так все await последовательно будут выполняться. Только после того когда они все закончатся будет вызван Take() S>>Другое дело если внутри есть ContinueWith или Task.Run S>Речь про произвольный код — по определению на это надо закладываться.
S>> Давай конкретный пример разберем. И в каком месте здесь дедлок S>ну это ж классика. Самый простой способ: S>
while (local1 == 0)
{
// Просто запускает делегат
// А он не выполнится пока ConsumerAsync() не сработает
// А он в твоем алгоритме стоит поле Produce
// И цикл крутится бесконечно
Produce(
() =>
{
Console.WriteLine(">local1++");
local1++;
Produce(a);
});
}
Но и в случае с ConsumerAsync() он вызывает Produce с тем же бесконечным циклом и ждет выполнения.
При этом до Console.WriteLine(">local1++"); он никогда не добирается.
А исклю
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>Правильнее по алгоритму сначала запустить чтение
Не спасёт.
S>// И цикл крутится бесконечно
Угу. Всего-то один умный человек решил, что if (local1 == 0) недостаточно кавайно, while понадёжней будет. Ну и последний Produce(a); убрал — while же есть.
Только чур не рассказывать, что такого не бывает, этим летом барабашку ловил. Чтоб было веселее — шедулер был не однопоточный, и оно таки со временем себя прожёвывало. Если никто больше проц не отжирал.
В общем, не надо изобретать велосипед, когда есть await. Проверено сложным способом
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Serginio1, Вы писали:
S>>Правильнее по алгоритму сначала запустить чтение S>Не спасёт.
S>>// И цикл крутится бесконечно S>Угу. Всего-то один умный человек решил, что if (local1 == 0) недостаточно кавайно, while понадёжней будет. Ну и последний Produce(a); убрал — while же есть.
S>Только чур не рассказывать, что такого не бывает, этим летом барабашку ловил. Чтоб было веселее — шедулер был не однопоточный, и оно таки со временем себя прожёвывало. Если никто больше проц не отжирал.
S>В общем, не надо изобретать велосипед, когда есть await. Проверено сложным способом
Прошу прощения писал в цктноте. Не до конца не разобрался
while (local1 == 0)
{
// Будет крутится в цикле пока не вызовется
// Этот делегат
Produce(
() =>
{
Console.WriteLine(">local1++");
local1++;
Produce(a);
});
}
Но он не выполнится ибо
Ждет выполнения првого, который крутит бесконечный цикл и ставит делегаты в очередь
while (true)
{
var nextItem = await m_data.Take();
nextItem.Invoke(); // Будет выполняться пока очередь не вызовет OutOfMemmory
}
Это по сути аналогично в одном потоке
event.WaitOne();
event.Set();
По сути это и есть дэдлок.
Аналогично будет и при использовании SynchronizationContext
А в данном примере задача будет использована только 1 раз
var nextItem = await m_data.Take();
Другое дело, что задачу топикастера, можно решать параллельные задачи с шедулером
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S> По сути это и есть дэдлок. S> Аналогично будет и при использовании SynchronizationContext
Бинго!
Про это и писал выше по ветке,
Для тасков так делать нельзя, дедлок | забитую очередь отхватить можно
...
Но топикстартеру надо "SynchronizationContext который бы сериализовал колбэки"...
Вызывать калбэки напрямую или ч/з await тут роли не играет, проблема с самими задачами.
Т.е. как только появляется необходимость запихнуть в одну очередь произвольный код — начинаются грабли.
S> Другое дело, что задачу топикастера, можно решать параллельные задачи с шедулером
Ну да. Или сами себе создаём проблемы с узким местом — очередью сообщений, или городим синхронизацию (и снова рискуем огрести из-за логической ошибки) или отказываемся от изменяемого разделяемого состояния вообще. Последнее как-то проще в итоге выходит.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Serginio1, Вы писали:
S>> По сути это и есть дэдлок. S>> Аналогично будет и при использовании SynchronizationContext
S>Бинго!
S>Про это и писал выше по ветке, S>
S>Для тасков так делать нельзя, дедлок | забитую очередь отхватить можно
S>...
S>Но топикстартеру надо "SynchronizationContext который бы сериализовал колбэки"...
S>Вызывать калбэки напрямую или ч/з await тут роли не играет, проблема с самими задачами.
S>Т.е. как только появляется необходимость запихнуть в одну очередь произвольный код — начинаются грабли.
Ну дык куча приложений работает с SynchronizationContext и никаких граблей не отхватывает. Та же 1С по такому принципу работает и дедлоков не отхватывает.
Просто для каждой задачи свой подход. Вплоть до разруливания дедлок аналогично как в SQL (Кодт помню выкладывал алгоритм).
S>> Другое дело, что задачу топикастера, можно решать параллельные задачи с шедулером S>Ну да. Или сами себе создаём проблемы с узким местом — очередью сообщений, или городим синхронизацию (и снова рискуем огрести из-за логической ошибки) или отказываемся от изменяемого разделяемого состояния вообще. Последнее как-то проще в итоге выходит.
Ну на самом деле у меня была задача при работе с Вацапом. Куча народу отправляли сообщения через один номер.
Отправлять нужно с задержками. В очереди может скапливаться по нескольку сообщений, но их недостаточно, что бы забить очередь до отказа.
и солнце б утром не вставало, когда бы не было меня