BV писал(а):TLS?
SLIM писал(а):Вот интересно, можно ли как-то "положить" что-нибудь в поток, и чтобы это принадлежало только ему при создании? Ну или после создания.
Что мешает передать указатель на данные, которые гарантированно не затрутся? Т.е. выделяем память, пишум туда что нужно, передаём в поток. Поток ими оперирует, а по завершении своей работы освобождает память.И все бы ничего, но передается то указатель на неизвестно что LPVOID. Да и черт бы с ним. Но вот что делать если по данному указателю данные поменялись?
Я не знаю на чём ты пишешь и как, но могу сказать одно: какое число ты передашь в lpParameter функции CreateThread, то и ляжет на стек при вызове процедуры потока. Т.е. проблемы вообще нет никакой, если пользоваться нормальными методами. Я бы сделал примерно так:Но передаем мы его адрес. Ну и получается, что значение переменной-итератора меняется быстрее чем поток скопирует его значение к себе в локальную переменную.
CloseHandle(CreateThread(
nil,
0,
@ThreadProc, // Адрес процедуры потока
pointer(your_array_index), // Кастуем любое передавамое значение к типу pointer и передаём
0,
nil
));
...
procedure ThreadProc(lpVoid: pointer); stdcall;
var
MyIndex: integer;
begin
// Получаем значение на стеке, кастуем к integer
MyIndex := integer(lpVoid);
end;
Twister писал(а):надо передавать не указатель на счётчик цикла, а само значение счётчика
Twister писал(а):Я тебя понял прекрасно. И уже показал в примере, что надо передавать не указатель на счётчик цикла, а само значение счётчика. В чём проблема-то?
Вам шашечки или ехать?Можно ли передавать индекс вместо указателя? Да, можно. Но мне кажется это ужасто некрасиво.
Что же передавать если нужно передать строку (массив). Только указатель. И что тогда будешь делать?
Twister писал(а):Но как быть, если нам нужно передать всего один dword? Лично мне кажется, что передавать указатель на него - вот это действительно некрасиво.
Twister писал(а):Я и про это уже говорил. Передавать указатель на те данные, которые гарантированно не изменятся.
Twister писал(а):ЗЫ. ИМХО, проблема высосана тобой из ничего. Чуток стоит подумать, не дольше минуты, и решение придёт само собой.
Ну позволю себе не согласиться. Все таки указатель - это указатель.
Что это за программист такой, который изменит функцию потока, не посмотрев, что в неё передаётся? Не надо приводить настолько надуманные примеры. Ну а уж если вам встретится такой программист, то следует гнать его подальше!Представь твой код попадет другому программисту. И тут он решает изменить ф-ю потока. Он ведь думает что передан указатель, начинает читать по этому указателю - а облом
Блин. Вот ты опять куда-то не туда полез. Какая потеря? Какой динамичности? О чём ты вообще?Т.е. откажись от динамичности кода. Если какая-то строка будет формироваться динамично, в процессе выполнения кода, и я не буду знать сколько таких строк будет - ну что вот тогда делать?
Twister писал(а):Что тут могло вызвать затруднения?
Twister писал(а):Задача: передать в поток указатель на данные. Данные по указателю могут измениться, нам же нужно гарантированно их доставить.
Решение: выделяем память; копируем туда все необходимые данные; создаём поток; передаём указатель на выделенную нами память; в потоке ловим указатель; по окончании работы с данными [или по завершению потока] освобождаем память.
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hThread = NULL;
LPTSTR pszMsg = NULL;
LPTSTR pszNum = NULL;
pszNum = (LPTSTR)calloc(sizeof(TCHAR)*10, sizeof(TCHAR));
for (int i=0; i<4; i++)
{
pszMsg = (LPTSTR)calloc(sizeof(TCHAR)*255, sizeof(TCHAR));
wcscpy(pszMsg, L"Это шаг ");
_itow(i, pszNum, 10);
wcscat(pszMsg, pszNum);
hThread = CreateThread(NULL, 0, ThreadkExecFn, pszMsg, 0, NULL);
CloseHandle(hThread);
hThread = NULL;
free(pszMsg);
}
free(pszNum);
MessageBox(NULL, L"конец", L"конец", MB_OK);
return 0;
}
DWORD WINAPI ThreadkExecFn(LPVOID pvParam)
{
MessageBox(NULL, (LPTSTR) pvParam, L"Сообщение", MB_OK);
return 0;
}
SLIM писал(а):4. Все, работа ф-ии окончена. Все что выделялось в ф-ии разрушено и более не существует и никому не нужно.
Так вот, пока система создаст поток, по указателю уже совсем не то что мы передавали - функция то уже завершилась, а поток еще работать не начал.
Хакер писал(а):У, блин, да ты трудный. Тебе говорят не разрушать и не освобождать память в конце функции. Подчёркнутый фрагмент из цитаты должен не быть истинным.
Прочувствуй разницу между выделением памяти (о котором я говорил) и резервированием её на стеке.4. Все, работа ф-ии окончена. Все что выделялось в ф-ии разрушено и более не существует и никому не нужно.
Twister писал(а):Прочувствуй разницу между выделением памяти (о котором я говорил) и резервированием её на стеке.
Хакер писал(а):У, блин, да ты трудный. Тебе говорят не разрушать и не освобождать память в конце функции. Подчёркнутый фрагмент из цитаты должен не быть истинным.
SLIM писал(а):С функцией неудачный пример. Лучше рассмотреть [url]что что[/url] я написал
SLIM писал(а):Это выглядит примерно так.
- Код: Выделить всё
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hThread = NULL;
LPTSTR pszMsg = NULL;
LPTSTR pszNum = NULL;
pszNum = (LPTSTR)calloc(sizeof(TCHAR)*10, sizeof(TCHAR));
for (int i=0; i<4; i++)
{
pszMsg = (LPTSTR)calloc(sizeof(TCHAR)*255, sizeof(TCHAR));
wcscpy(pszMsg, L"Это шаг ");
_itow(i, pszNum, 10);
wcscat(pszMsg, pszNum);
hThread = CreateThread(NULL, 0, ThreadkExecFn, pszMsg, 0, NULL);
CloseHandle(hThread);
hThread = NULL;
free(pszMsg);
}
free(pszNum);
MessageBox(NULL, L"конец", L"конец", MB_OK);
return 0;
}
DWORD WINAPI ThreadkExecFn(LPVOID pvParam)
{
MessageBox(NULL, (LPTSTR) pvParam, L"Сообщение", MB_OK);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hThread = NULL;
LPTSTR pszMsg = NULL;
LPTSTR pszNum = NULL;
pszNum = (LPTSTR)calloc(sizeof(TCHAR)*10, sizeof(TCHAR));
for (int i=0; i<4; i++)
{
pszMsg = (LPTSTR)calloc(sizeof(TCHAR)*255, sizeof(TCHAR));
wcscpy(pszMsg, L"Это шаг ");
_itow(i, pszNum, 10);
wcscat(pszMsg, pszNum);
hThread = CreateThread(NULL, 0, ThreadkExecFn, pszMsg, 0, NULL);
CloseHandle(hThread);
hThread = NULL;
// free(pszMsg); // FIXED: Идиотизм
}
free(pszNum)
MessageBox(NULL, L"конец", L"конец", MB_OK);
return 0;
}
DWORD WINAPI ThreadkExecFn(LPVOID pvParam)
{
MessageBox(NULL, (LPTSTR) pvParam, L"Сообщение", MB_OK);
free(pvParam); // FIXED: Надо здесь
return 0;
}
SLIM писал(а):Вы предлагаете ... переложить высвобождение памяти по этому указателю на поток?
Вернуться в Windows-программирование
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1