powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / CreateThread - проблемы выполнения
25 сообщений из 42, страница 1 из 2
CreateThread - проблемы выполнения
    #35480307
Где то там
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот кусок кода, с помощью которого я вызываю диалог на время выполнения операции. При инициализации, диалог отдает свой хэндл, чтобы потом его можно было закрыть. Но это происходит не всегда. В чём может быть причина?

var
hPreLoad : HWND;
Dummy : DWORD;
hThread : HWND;

//---------------------------------------------------------

function PreLoadDialogProc(hWndDlg : HWND; Msg : Longint; wParam, lParam : Longint) : Boolean; stdcall;
begin
Result := False;
case Msg of
// не всегда выполняется
WM_INITDIALOG : hPreLoad := hWndDlg;
WM_COMMAND:
case LOWORD(wParam) of
IDOK,
IDCANCEL : EndDialog(hWndDlg, ord(True));
end;
end;
end;

//---------------------------------------------------------

procedure PreLoadDialogThread;
begin
DialogBox(hInstance, 'ID_PRELOADDLG', 0, @PreLoadDialogProc);
end;

//---------------------------------------------------------

begin
...
hThread := CreateThread(NIL, 0, @PreLoadDialogThread, NIL, 0, Dummy);
... // выполняемая задача
SendMessage(hPreLoad, WM_COMMAND, IDOK, 0); // Не всегда hPreload известен, иногда 0
hPreload := 0;
if hThread <> 0 then
begin
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
hThread := 0;
end;
...
end;
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480310
Где то там
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Жаль отредактировать нельзя, забыл выделить кодом.
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480317
C#C++
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Типичная ошибка многопоточного программирования ))
hPreLoad во втором потоке не успевает инициализироваться перед тем, как его использует SendMessage в первом.
Используйте Event (функции CreateEvent, SetEvent и WaitForSingleObject, см. хелп)

Кстати, PreLoadDialogThread должна быть функцией
function PreLoadDialogThread(p:DWORD):DWORD
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480328
Где то там
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторКстати, PreLoadDialogThread должна быть функцией
function PreLoadDialogThread(p:DWORD):DWORD

Ну она и так функция. Нигде не сказано, что я не могу объявить её Boolean. А вот про Event нужно почитать, чем он в данном случае лучше.
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480330
Где то там
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прошу прощения, не туда глянул.
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480337
Где то там
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Просмотрел SDK, MSDN, а также исходники Delphi, но ничего применительно к моему случаю не нашёл. Если не сложно, напишите скелет кода, как это сделать.
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480365
C#C++
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Где то тамПросмотрел SDK, MSDN, а также исходники Delphi, но ничего применительно к моему случаю не нашёл. Если не сложно, напишите скелет кода, как это сделать.
Вот, ваш код + event (вставки - желтым)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
 var 
hPreLoad : HWND;
Dummy : DWORD;
hThread : HWND;
hEvent: HANDLE;

 //--------------------------------------------------------- 

 function  PreLoadDialogProc(hWndDlg : HWND; Msg : Longint; wParam, lParam : Longint) : Boolean; stdcall;
 begin 
Result := False;
 case  Msg  of 
 // не всегда выполняется 
WM_INITDIALOG : hPreLoad := hWndDlg;
          SetEvent(hEvent);  // переводим событие в сигнальное состояние 
WM_COMMAND:
 case  LOWORD(wParam)  of 
IDOK,
IDCANCEL : EndDialog(hWndDlg, ord(True));
 end ;
 end ;
 end ;

 //--------------------------------------------------------- 

 procedure  PreLoadDialogThread;
 begin 
DialogBox(hInstance, 'ID_PRELOADDLG',  0 , @PreLoadDialogProc);
 end ;

 //--------------------------------------------------------- 

 begin 
...
  //создаем событие в несигнальном состоянии 
hEvent := CreateEvent( NIL ,  0 ,  0 ,  NIL );
hThread := CreateThread( NIL ,  0 , @PreLoadDialogThread,  NIL ,  0 , Dummy);
...  // выполняемая задача 

  // ждем перехода события в сигнальное состояние, после чего убиваем за ненадобностью 
WaitForSingleObject(hEvent, INFINITE);  CloseHandle(hEvent); hEvent :=  0 ;
SendMessage(hPreLoad, WM_COMMAND, IDOK,  0 );  // Не всегда hPreload известен, иногда 0 
hPreload :=  0 ;
 if  hThread <>  0   then 
 begin 
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
hThread :=  0 ;
 end ;
...
 end ;
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480380
Где то там
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
То-то я из исходников Delphi ничего не мог понять. Везде CreateEvent идет в паре с CreateThread, а из сказанного Вами ранее я понял, что от CreateThread нужно избавляться. Спасибо за помощь.
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480735
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где то тамя понял, что от CreateThread нужно избавляться.

Да мне вот тоже странно: зачем тут поток, если его окончания ждут по
WaitForSingleObject...
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480782
Где то там
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
Где то тамя понял, что от CreateThread нужно избавляться.

Да мне вот тоже странно: зачем тут поток, если его окончания ждут по
WaitForSingleObject...
Posted via ActualForum NNTP Server 1.4

А разве в MSDN описано по другому?
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480802
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где то тамА разве в MSDN описано по другому?

Неужели в MSDN написано, что диалоги можно показывать только в отдельном
потоке?

Обычно завершения потоков вообще не ждут...
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480844
Где то там
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну вообще так написано в MSDN и так делает Borland. И всем им не верить?
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480886
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где то там
так написано в MSDN и так делает Borland. И всем им не верить?

Точные цитаты, пожалуйста, в студию! Мне уже интересно, где это ты нашёл
у Борланда диалоги в потоках.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480905
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov> Мне уже интересно, где это ты нашёл у Борланда диалоги в потоках.




Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480920
Где то там
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В исходники Delphi пожалуйста.
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35480941
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где то тамВ исходники Delphi пожалуйста.

Miln"Url, url." - said Owl.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35481098
C#C++
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry SibiryakovДа мне вот тоже странно: зачем тут поток, если его окончания ждут по
WaitForSingleObject...Посмотри внимательно код:
Код: plaintext
1.
2.
hThread := CreateThread( NIL ,  0 , @PreLoadDialogThread,  NIL ,  0 , Dummy);
...  // выполняемая задача 
Пока диалог на экране, в родительском потоке выполняются действия, после которых подается команда завершения диалога.

Как я понимаю, WaitForSingleObject(hThread, INFINITE); здесь используется только для того, чтоб вызвать CloseHandle(hThread); после завершения потока. Но это совсем необязательно, если закрыть hThread сразу, то с работающим потоком ничего не произойдёт (почему - см. Рихтер). Так что вполне можно сделать так:
Код: plaintext
1.
CloseHandle(CreateThread( NIL ,  0 , @PreLoadDialogThread,  NIL ,  0 , Dummy));
и убрать из кода все строки, где есть hThread
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35481138
Где то там
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
C#C++
Пока диалог на экране, в родительском потоке выполняются действия, после которых подается команда завершения диалога.

Именно так.

C#C++
Как я понимаю, WaitForSingleObject(hThread, INFINITE); здесь используется только для того, чтоб вызвать CloseHandle(hThread); после завершения потока. Но это совсем необязательно, если закрыть hThread сразу, то с работающим потоком ничего не произойдёт (почему - см. Рихтер). Так что вполне можно сделать так:
Код: plaintext
1.
CloseHandle(CreateThread( NIL ,  0 , @PreLoadDialogThread,  NIL ,  0 , Dummy));
и убрать из кода все строки, где есть hThread

А поточнее? Имеется в виду это:

было
Код: plaintext
1.
    hThread := CreateThread( NIL ,  0 , @PreLoadDialogThread, Pointer(hWndDlg),  0 , Dummy);
стало
Код: plaintext
1.
    CreateThread( NIL ,  0 , @PreLoadDialogThread, Pointer(hWndDlg),  0 , Dummy);
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #35481156
C#C++
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Где то тамА поточнее? Имеется в виду это:

было
Код: plaintext
1.
    hThread := CreateThread( NIL ,  0 , @PreLoadDialogThread, Pointer(hWndDlg),  0 , Dummy);
стало
Код: plaintext
1.
    CreateThread( NIL ,  0 , @PreLoadDialogThread, Pointer(hWndDlg),  0 , Dummy);
Имеется ввиду, что если не нужен дескриптор потока, то CloseHandle можно вызвать сразу после создания потока, на сам поток это никак не повлияет.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
CreateThread - проблемы выполнения
    #39985454
Не хочется создавать тему ради пары дилетантских вопросов. Немного некромантии.

1. Как в Beginthread/Createthread корректно вызвать процедуру в главном потоке для синхронизации и обновления формы. Synchronize вроде как не вызвать, критическая секция не особо подходит. Сообщение? Событие? Ещё как-то?

2. Тут http://www.delphibasics.ru/BeginThread.php пишут
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
ThreadVar         // Мы должны позволить каждому потоку его собственные образцы
                  // переданной переменной записи
  msgPtr : ^TMsgRecord;
function ShowMsg(Parameter : Pointer) : Integer;
begin
  // Указываем указатель на переданные данные
  // Обратите внимание, что каждый поток имеет отдельную копию msgPtr
  msgPtr := Parameter;
...

Но ^TMsgRecord указатель на тот же участок памяти, отдельных копий же нет? То есть если дальше в главном потоке или в другом потоке что-то меняется, то меняется везде?

Почему не делают так?
Код: pascal
1.
2.
3.
4.
5.
ThreadVar  
  msgPtr : TMsgRecord;
function ShowMsg(Parameter : Pointer) : Integer;
begin
  msgPtr := TMsgRecord(Parameter^);


Или я просто не понял чего-то.
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #39985456
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Или я просто не понял чего-то.

Видимо
Код: plaintext
1.
2.
3.
 [code=pascal]
threadvar
x : integer;



declares an integer type variable that is private to each thread in the application, but global within each thread.
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #39985468
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Но ^TMsgRecord указатель на тот же участок памяти, отдельных копий же нет?
Именно отдельные копии и будут для каждого потока при threadvar.
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #39985469
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич
Как в Beginthread/Createthread корректно вызвать процедуру в главном потоке для синхронизации и обновления формы. Synchronize вроде как не вызвать
Так же, как и всегда - Send/PostMessage.
Если, не смотря на все проблемы, таки очень хочется Synchronize - можно написать TThread.Synchronize и передать туда чей-то метод.
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #39985496
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock
Андрей Игоревич
Как в Beginthread/Createthread корректно вызвать процедуру в главном потоке для синхронизации и обновления формы. Synchronize вроде как не вызвать
Так же, как и всегда - Send/PostMessage.
Если, не смотря на все проблемы, таки очень хочется Synchronize - можно написать TThread.Synchronize и передать туда чей-то метод.


Если Delphi современная, то можно передать анонимную процедуру.
...
Рейтинг: 0 / 0
CreateThread - проблемы выполнения
    #39985584
YuRock
Андрей Игоревич
Но ^TMsgRecord указатель на тот же участок памяти, отдельных копий же нет?
Именно отдельные копии и будут для каждого потока при threadvar.

Но ^TMsgRecord это же копия указателя, это не "Integer" и не полноценная переменная.

Ну просто для понимания тестовый пример:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
type
  TData = record
    Data1:integer;
    Data2:extended;
    Data3:String[30];
  end;
var
    DataToThread:TData;
ThreadVar
    LocalData:^TData;
    MessageData:TMessageData;

function TestThread1(Prarameters:Pointer): Integer;
Begin
  Result := 0;
  LocalData := Prarameters;
  LocalData.Data1 := 4321;
  Sleep(200);
  //...
  Sendmessage (MainHandle, WM_DATA_UPDATE, 123, Integer(@MessageData) );
  EndThread(0);
End;

function TestThread2(Prarameters:Pointer): Integer;
Begin
  Result := 0;
  Sleep(100);
  LocalData := Prarameters;
  LocalData.Data1 := 1234;
  //...
  Sendmessage (MainHandle, WM_DATA_UPDATE, 321, Integer(@MessageData) );
  EndThread(0);
End;

procedure TForm1.Button1Click(Sender: TObject);
begin
   DataToTread.Data1 := 0;
   TreadHeandle1 := BeginThread  (nil, 0, @TestThread1, @DataToThread, 0, id1);
   TreadHeandle2 := BeginThread  (nil, 0, @TestThread2, @DataToThread, 0, id2);
   sleep(500);

   Memo1.Lines.Add(DataToTread.Data1.ToString);
   CloseHandle(TreadHeandle1);
   CloseHandle(TreadHeandle2);
end;



Суть кода выше:

По нажатии кнопки присваиваю глобальной переменной
Код: pascal
1.
DataToTread.Data1 := 0;


Передаю в поток 1 и 2 @DataToTread
Далее в потоке 1 "вроде как" локальной копии присваиваю значение
Код: pascal
1.
LocalData.Data1 := 4321;


В потоке 2 жду 100мс (дабы первый поток успел присвоить) и делаю
Код: pascal
1.
LocalData.Data1 := 1234;



В главном потоке жду пока всё закончиться sleep(500);
Вывожу глобальную переменную
Код: pascal
1.
Memo1.Lines.Add(DataToTread.Data1.ToString);


И вижу
Memo11234
Если бы там были локальные переменные, такого бы не произошло, осталось бы значение 0. Или я всё ещё продолжаю что-то не понимать.
...
Рейтинг: 0 / 0
25 сообщений из 42, страница 1 из 2
Форумы / Delphi [игнор отключен] [закрыт для гостей] / CreateThread - проблемы выполнения
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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