Re: Странности foreach при параллельной работе
От: -n1l-  
Дата: 30.04.16 16:29
Оценка: +2
Try — Catch'a нет нигде.
Поток валиться с ошибкой и просто не выполняется.
Re[2]: Странности foreach при параллельной работе
От: abb269  
Дата: 30.04.16 16:37
Оценка: 22 (1)
Здравствуйте, Sinix, Вы писали:
S>1. зачем вам вообще таски, если вы ограничиваете конкурентность до одного потока?
На входе разная информация, разные ключи, думал для быстродействия разделить обработку, тем более, что она впрямую не связана
S>2. Как вы проверяете, что таски действительно выполняются в одном потоке?
Такой проверки нету, верю микрософту и его примеру
S>3. Как вы гарантируете, что с sw работает только один поток?
Я (далеко не самый знающий человек) понимаю так: в данный обработчик попадают только данные с ключом key1, причем уровень параллельности 1, т.е. новый пакет данных ждет, пока не закончится обработка старого. Значит, я думаю, что с файлом работает только один поток.
S>4. В каком окружении выполняется код? отдельный сервис, iis, ещё что-то?
Самый сложный вопрос. Это десктоповское приложение...
S>5. Вызывает ли ваш код Thread.Abort()?
Нет, впрямую такую конструкцию не использую
Re[3]: Странности foreach при параллельной работе
От: -n1l-  
Дата: 30.04.16 17:46
Оценка: +1
Попробуй операции выполнить в одном потоке.
Re[5]: Странности foreach при параллельной работе
От: Lexey Россия  
Дата: 30.04.16 19:14
Оценка: +1
Здравствуйте, abb269, Вы писали:

A>И еще вопрос. Хочу попробовать для увеличения быстродействия конструкции просто распараллелить обработку в алгоритмах. Можно ли просто в лоб вместо просто foreach


A>Parallel.ForEach(aList, a => { a.GetHandler(); });


Зависит от того, что делают GetHandler'ы. Если они не модифицируют разделяемое состояние, то можно так параллелить.
"Будь достоин победы" (c) 8th Wizard's rule.
Странности foreach при параллельной работе
От: abb269  
Дата: 30.04.16 14:11
Оценка:
Здравствуйте,
Тут вот какая проблема. Есть консольное приложение для обработки данных.
Часть важных данных, порядок следования которых критичен, обрабатывается в отдельном потоке
через LimitedConcurrencyLevelTaskScheduler (ссылка https://msdn.microsoft.com/en-us/library/ee789351%28v=vs.100%29.aspx)

        private static readonly TaskScheduler key1ts = 
            new LimitedConcurrencyLevelTaskScheduler(1);

        private static void NewData(string data)
        {
            Data d = new Data();
            d.line = data;
            
            if (data.StartsWith("key1"))
            {
                Task.Factory.StartNew(
                    GetKey1Handler,
                    d,
                    CancellationToken.None,
                    TaskCreationOptions.None,
                    key1ts);
                return;
            }
    }


С другой стороны есть несколько алгоритмов обработки этих данных (экземпляров класса Algo)
Управление в эти алгоритмы передается так

        private static void GetKey1Handler(object o)
        {
            Data d = (Data)o;

            tD.par1 = d.line;
            tD.par2 = d.line;
            
            int ii = 0;
            
            for (int i = 0; i < 10; i++)
            {
                ii++;
                foreach (Algo a in aList)
                {
                    a.GetHandler();
                }
                sw.WriteLine(ii);
                sw.Flush();
            }
        }


Очень странно, но при некоторых неблагоприятных условиях (долгая обработка в a.GetHandler) в файл sw попадют не все значения ii.
Я это понимаю так, что новая порция данных сбивает обработку, а сама куда-то исчезает.
Все мои попытки воспроизвести ситуацию на упрощенном примере ни к чему не приводят: в файле sw последовательное перечисление индекса.
Но боевой вариант точно где-то сбоит: в логе обрыв на полуслове обработки в отдельном хэндлере, а в файле не все значения ii.
Есть какие-то мысли почему так происходит?
Отредактировано 30.04.2016 14:21 abb269 . Предыдущая версия .
Re: Странности foreach при параллельной работе
От: Sinix  
Дата: 30.04.16 16:15
Оценка:
Здравствуйте, abb269, Вы писали:


A>Есть какие-то мысли почему так происходит?

Что-то пошло не так, большего по вопросу не поймёшь.

Начнём с самого простого:
1. зачем вам вообще таски, если вы ограничиваете конкурентность до одного потока?
2. Как вы проверяете, что таски действительно выполняются в одном потоке?
3. Как вы гарантируете, что с sw работает только один поток?
4. В каком окружении выполняется код? отдельный сервис, iis, ещё что-то?
5. Вызывает ли ваш код Thread.Abort()?
Re[2]: Странности foreach при параллельной работе
От: abb269  
Дата: 30.04.16 16:40
Оценка:
Здравствуйте, -n1l-, Вы писали:

N>Try — Catch'a нет нигде.

N>Поток валиться с ошибкой и просто не выполняется.

Я пытался отловить исключение. Try ничего не ловит, код просто тихо глотает данные.
Re[3]: Странности foreach при параллельной работе
От: Sinix  
Дата: 30.04.16 17:39
Оценка:
Здравствуйте, abb269, Вы писали:

A>На входе разная информация, разные ключи, думал для быстродействия разделить обработку, тем более, что она впрямую не связана


А, дошло. В теории должно работать, если нет косяков в самом шедулере. При беглом просмотре их не наблюдается, остаётся только случай "ваш код бросает исключение".

Как вариант, можно пока заменить шедулер на что-то типа такого. Если проблема исчезнет — будет понятно, куда копать дальше. Если не исчезнет — тем более понятно.

Ну и отладочный логгинг исключений ч/з AppDomain.FirstChanceException event сделать, если ещё не.


A>Значит, я думаю, что с файлом работает только один поток.

Ну а другие участки кода к sw доступа точно не имеют? Если имеют — проверить, что они не пытаются записать что-то параллельно.

Для контроля в начале GetKey1Handler:
var check = Interlocked.Increment(ref concurrencyCount); // static int field
в конце, в finally,
Interlocked.Decrement(ref concurrencyCount);

если check > 1 — у вас проблемы c шедулингом.


S>>4. В каком окружении выполняется код? отдельный сервис, iis, ещё что-то?

A>Самый сложный вопрос. Это десктоповское приложение...
Угу, тогда половина потенциальных проблем отпадает.
Re[4]: Странности foreach при параллельной работе
От: abb269  
Дата: 30.04.16 18:19
Оценка:
Sinix, Большое спасибо, буду пробовать.
И еще вопрос. Хочу попробовать для увеличения быстродействия конструкции просто распараллелить обработку в алгоритмах. Можно ли просто в лоб вместо просто foreach

Parallel.ForEach(aList, a => { a.GetHandler(); });
Отредактировано 30.04.2016 18:55 abb269 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.