|
Почему многопоточный код выполняется по-разному?
|
|||
---|---|---|---|
#18+
Все потоки ведут чтение из одного массива x, а затем результат записывают в ячейки другого массива y, каждый поток записывает лишь свою группу элементов массива y. while(условие){ Thread[] t = new Thread[4]; for(int i = 0; i < 4; i++){ t[i] = new Thread(() => { f(i); } ); t[i].Start(); } for(int i = 0; i < 4; i++) t[i].Join(); // !!! Сюда мы не должны заходить, пока не выполнятся все 4 потока или всё-таки можем? // я ожидаю, что здесь все потоки из Thread[] t сделают своё дело // условие цикла while пересчитывается заново // Здесь также выводятся на экран промежуточные вычисления } Почему на экран выводятся разные промежуточные вычисления при одном и том же выполнении кода? И можем ли мы зайти на строчку (!!!) до того, как выполнятся все 4 потока? ... |
|||
:
Нравится:
Не нравится:
|
|||
16.07.2013, 20:54 |
|
Почему многопоточный код выполняется по-разному?
|
|||
---|---|---|---|
#18+
... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2013, 11:05 |
|
Почему многопоточный код выполняется по-разному?
|
|||
---|---|---|---|
#18+
ayvango, изучите механизм async/await — там вам будет понятней чего и почему. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2013, 11:07 |
|
Почему многопоточный код выполняется по-разному?
|
|||
---|---|---|---|
#18+
ayvango, проблема кроется в использовании переменной цикла в лямбде. Вычисление лямбды происходит не сразу и может получиться что для разных потоков значение i будет одинаковым. Захват локальной переменной внутри лямбды называется замыканием (closure) и надо что это такое и как оно работает. Прочитай Замыкания в языке программирования C# В данном случае чтобы исправить код можно применить два подхода. 1. Ввести временную переменную: Код: c# 1. 2. 3. 4. 5. 6. 7.
2. Использовать делегат ParameterizedThreadStart. Это потребует немного изменить функцию f() Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
Я бы предпочел вариант №2. ayvangoИ можем ли мы зайти на строчку (!!!) до того, как выполнятся все 4 потока? Нет. Вызов Join() гарантирует что пока все созданные тобой потоки не завершат свою работу строка !!! не начнет выполняться. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2013, 12:47 |
|
Почему многопоточный код выполняется по-разному?
|
|||
---|---|---|---|
#18+
bazile, решарпер, кстати, в случаях захвата переменной цикла выдаёт предупреждение :) эта проблема касается не только многопоточного программирования, но и в целом при работе с лямбдами в циклах. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2013, 12:51 |
|
Почему многопоточный код выполняется по-разному?
|
|||
---|---|---|---|
#18+
bazile, во втором случае объявлять локальную переменную внутри функции не требуется. во-первых совсем не обязательно делать упаковку в object, во-вторых переменная итак будет создана на стеке и проблема решится. т.е. это два слоя масла-маслянного :) ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2013, 12:53 |
|
Почему многопоточный код выполняется по-разному?
|
|||
---|---|---|---|
#18+
hVosttрешарпер, кстати, в случаях захвата переменной цикла выдаёт предупреждение :) Мы не знаем есть ли решарпер у ayvango :) hVosttво втором случае объявлять локальную переменную внутри функции не требуется. во-первых совсем не обязательно делать упаковку в object Приведи код как при использовании ParameterizedThreadStart избежать упаковки. Модератор: Тема перенесена из форума "ASP.NET". ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2013, 13:12 |
|
Почему многопоточный код выполняется по-разному?
|
|||
---|---|---|---|
#18+
bazilehVosttво втором случае объявлять локальную переменную внутри функции не требуется. во-первых совсем не обязательно делать упаковку в object Приведи код как при использовании ParameterizedThreadStart избежать упаковки. упаковки избежать не получится с делегатом, точняк. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2013, 13:23 |
|
Почему многопоточный код выполняется по-разному?
|
|||
---|---|---|---|
#18+
bazile, спасибо за подробный ответ и за понятную ссылку. Если я правильно понял, то для кода Код: c# 1. 2. 3. 4. 5. 6. 7. 8.
Надо лишь заменить i на temp, поскольку остальные переменные либо являются переменными внутреннего цикла анонимного метода(как j), либо одинаковы для каждого потока (как z) Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9.
И основная проблема именно к привязке к переменной i, а не к её значению, что и устраняется в исправленном коде. Всё верно? ... |
|||
:
Нравится:
Не нравится:
|
|||
18.07.2013, 04:33 |
|
|
start [/forum/topic.php?fid=20&msg=38335418&tid=1404340]: |
0ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
67ms |
get topic data: |
12ms |
get forum data: |
2ms |
get page messages: |
54ms |
get tp. blocked users: |
2ms |
others: | 13ms |
total: | 181ms |
0 / 0 |