Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Почему многопоточный код выполняется по-разному? / 10 сообщений из 10, страница 1 из 1
16.07.2013, 20:54
    #38333432
ayvango
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему многопоточный код выполняется по-разному?
Все потоки ведут чтение из одного массива 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 потока?
...
Рейтинг: 0 / 0
17.07.2013, 11:05
    #38333768
hVostt
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему многопоточный код выполняется по-разному?
...
Рейтинг: 0 / 0
17.07.2013, 11:07
    #38333771
hVostt
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему многопоточный код выполняется по-разному?
ayvango,

изучите механизм async/await — там вам будет понятней чего и почему.
...
Рейтинг: 0 / 0
17.07.2013, 12:47
    #38333953
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему многопоточный код выполняется по-разному?
ayvango, проблема кроется в использовании переменной цикла в лямбде. Вычисление лямбды происходит не сразу и может получиться что для разных потоков значение i будет одинаковым. Захват локальной переменной внутри лямбды называется замыканием (closure) и надо что это такое и как оно работает. Прочитай Замыкания в языке программирования C#

В данном случае чтобы исправить код можно применить два подхода.

1. Ввести временную переменную:
Код: c#
1.
2.
3.
4.
5.
6.
7.
Thread[] t = new Thread[4];
for (int i = 0; i < 4; i++)
{
    int temp = i;
    t[i] = new Thread(() => { f(temp); } );
    t[i].Start();
}



2. Использовать делегат ParameterizedThreadStart. Это потребует немного изменить функцию f()
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Thread[] t = new Thread[4];
for (int i = 0; i < 4; i++)
{
    t[i] = new Thread(f);
    t[i].Start(i);
}
...
void f(object data)
{
    int idx = (int) data;
    ...
}



Я бы предпочел вариант №2.

ayvangoИ можем ли мы зайти на строчку (!!!) до того, как выполнятся все 4 потока?
Нет. Вызов Join() гарантирует что пока все созданные тобой потоки не завершат свою работу строка !!! не начнет выполняться.
...
Рейтинг: 0 / 0
17.07.2013, 12:51
    #38333966
hVostt
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему многопоточный код выполняется по-разному?
bazile,

решарпер, кстати, в случаях захвата переменной цикла выдаёт предупреждение :) эта проблема касается не только многопоточного программирования, но и в целом при работе с лямбдами в циклах.
...
Рейтинг: 0 / 0
17.07.2013, 12:53
    #38333974
hVostt
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему многопоточный код выполняется по-разному?
bazile,

во втором случае объявлять локальную переменную внутри функции не требуется. во-первых совсем не обязательно делать упаковку в object, во-вторых переменная итак будет создана на стеке и проблема решится. т.е. это два слоя масла-маслянного :)
...
Рейтинг: 0 / 0
17.07.2013, 13:12
    #38334023
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему многопоточный код выполняется по-разному?
hVosttрешарпер, кстати, в случаях захвата переменной цикла выдаёт предупреждение :)
Мы не знаем есть ли решарпер у ayvango :)

hVosttво втором случае объявлять локальную переменную внутри функции не требуется. во-первых совсем не обязательно делать упаковку в object
Приведи код как при использовании ParameterizedThreadStart избежать упаковки.

Модератор: Тема перенесена из форума "ASP.NET".
...
Рейтинг: 0 / 0
17.07.2013, 13:23
    #38334047
hVostt
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему многопоточный код выполняется по-разному?
bazilehVosttво втором случае объявлять локальную переменную внутри функции не требуется. во-первых совсем не обязательно делать упаковку в object
Приведи код как при использовании ParameterizedThreadStart избежать упаковки.

упаковки избежать не получится с делегатом, точняк.
...
Рейтинг: 0 / 0
18.07.2013, 04:33
    #38334992
ayvango
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему многопоточный код выполняется по-разному?
bazile,

спасибо за подробный ответ и за понятную ссылку.

Если я правильно понял, то для кода

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
int z = h();
Thread[] t = new Thread[4];
for (int i = 0; i < 4; i++)
{
    t[i] = new Thread(() => { for(int j = i; j < 1000; ++j) g(i, j, z); } );
    t[i].Start();
}
for (int i = 0; i < 4; i++) t[i].Join()



Надо лишь заменить i на temp, поскольку остальные переменные либо являются переменными внутреннего цикла анонимного метода(как j), либо одинаковы для каждого потока (как z)

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
int z = h();
Thread[] t = new Thread[4];
for (int i = 0; i < 4; i++)
{
    int temp = i;
    t[i] = new Thread(() => { for(int j = temp; j < 1000; ++j) g(temp, j, z); } );
    t[i].Start();
}
for (int i = 0; i < 4; i++) t[i].Join()


И основная проблема именно к привязке к переменной i, а не к её значению, что и устраняется в исправленном коде. Всё верно?
...
Рейтинг: 0 / 0
18.07.2013, 12:56
    #38335418
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему многопоточный код выполняется по-разному?
ayvangoИ основная проблема именно к привязке к переменной i, а не к её значению, что и устраняется в исправленном коде. Всё верно?
Да.
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Почему многопоточный код выполняется по-разному? / 10 сообщений из 10, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]