powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Почему многопоточный код выполняется по-разному?
10 сообщений из 10, страница 1 из 1
Почему многопоточный код выполняется по-разному?
    #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
Почему многопоточный код выполняется по-разному?
    #38333768
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Почему многопоточный код выполняется по-разному?
    #38333771
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvango,

изучите механизм async/await — там вам будет понятней чего и почему.
...
Рейтинг: 0 / 0
Почему многопоточный код выполняется по-разному?
    #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
Почему многопоточный код выполняется по-разному?
    #38333966
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bazile,

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

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

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

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

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


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