Текущий архив: 2005.06.14;
Скачать: CL | DM;
ВнизКак сделать чтобы форма реагировала во время работы потоков. Найти похожие ветки
← →
Alex Konshin © (2005-05-27 14:14) [40]Digitman © (27.05.05 14:10) [39]
> Alex Konshin © (27.05.05 14:04) [38]
ну эт ты загнул)
прерваны они, конечно, м.б., но только не одиночные (т.е. если используется REPХХ-префикс)
А я и сказал цепочечные операции. И опять-таки не забывай, что значения в регистрах должны как-то оказаться, т.е. одиночной командой ты не обойдешься. А они вместе уж всяко не будут атомарными.
← →
Digitman © (2005-05-27 14:21) [41]
> Alex Konshin © (27.05.05 14:14) [40]
> значения в регистрах должны как-то оказаться
ну мы ж - конкретно о LODS/STOS/MOVS/CMPS)... а не об иных инструкциях, которые нужны для начальной инициализации используемых цеп.инструкциями регистров
← →
Anatoly Podgoretsky © (2005-05-27 14:21) [42]Digitman © (27.05.05 14:10) [39]
А это уже означает агрегатные, они к тому же еще и чрезвычайно медленные на современных процессорах. Хорощо что Борланд не купился на них в своем компиляторе.
← →
Alex Konshin © (2005-05-27 14:36) [43]Digitman © (27.05.05 14:21) [41]
ну мы ж - конкретно о LODS/STOS/MOVS/CMPS)... а не об иных инструкциях, которые нужны для начальной инициализации используемых цеп.инструкциями регистров
В таком случае почти все инструкции - атомарные. Кроме тех, что с двойным обращением к памяти (к некоторым из них и можно применить lock). Только Delphi-то от этого какой прок?
Кстати, movs с двойным обращением, нужно еще посмотреть, что там про нее написано, скорее всего это и не атомарная инструкция вовсе, неясно, что же будет при паралельном обращении другим процессором к ячейке, в которую мы пишем.
← →
Digitman © (2005-05-27 14:43) [44]
> Anatoly Podgoretsky © (27.05.05 14:21) [42]
> Хорощо что Борланд
> не купился на них в своем компиляторе
в смысле ?
← →
GuAV © (2005-05-27 22:11) [45]Anatoly Podgoretsky © (27.05.05 14:21) [42]
не купился на них
?
var
A, B: array[Byte] of Byte;
C, D: array[0..19] of Byte;
A := B;
lea esi,[esp+$00000100]
mov edi,esp
mov ecx,$00000040
rep movsd
C := D;
lea esi,[esp+$00000214]
lea edi,[esp+$00000200]
movsd
movsd
movsd
movsd
movsd
← →
Defunct © (2005-05-28 00:02) [46]GuAV © (27.05.05 22:11) [45]
Все иногда ошибаются.
Насчет атомарности mov, и строковых операций movs, lods, stos, scas, cmps:
склоняюсь к тому, что все эти инструкции являются атомарными в чистом виде. Так как не используется метод чтение-модификация-запись.
← →
Verg © (2005-05-28 07:21) [47]В многопроцессорных системах разделение шины арбитром происходит между циклами шины.
Сколько циклов шины займет атомарная на первый взгляд операция mov [ebx], eax если, например, ebx = 0x789FF ?
← →
isasa © (2005-05-28 10:39) [48]procedure TMyThread1.DoWork;
begin
Form1.CheckBox.Checked := True;
end;
Ну соотвественно второй
Form1.CheckBox.Checked := False;
В многопоточном варианте эта конструкция не есть гуд.
Надо использовать SendMessage.
← →
-=XP=- © (2005-05-28 10:48) [49]В многопоточном варианте эта конструкция не есть гуд.
Надо использовать SendMessage.
Можете пояснить?
← →
isasa © (2005-05-28 11:17) [50]Опять же. Вот фрагмент из Делф. хелп файла
($DELPHI)\Common Files\Borland Shared\MSHelp\WIN32.HLP
The SendMessage function sends the specified message to a window or windows. The function calls the window procedure for the specified window and does not return until the window procedure has processed the message. The PostMessage function, in contrast, posts a message to a thread"s message queue and returns immediately.
LRESULT SendMessage(
HWND hWnd, // handle of destination window
UINT Msg, // message to send
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
Parameters
hWnd
Identifies the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows.
Msg
Specifies the message to be sent.
wParam
Specifies additional message-specific information.
lParam
Specifies additional message-specific information.
Return Values
The return value specifies the result of the message processing and depends on the message sent.
Где "handle of destination window" Form.Handle
Классики не рекомендуют использовать прямую адресацию между потоками. Жотя здесь маршаллинг не нужен.
Кстати, меня гложет сомнения, что все это работает отдельными потоками.
Я пользуюсь функцией CreateThread (и не заморачиваюсь на TThread)
TmainForm = class(TForm)
...
private
aThreads : aTHandle;
aThreadIDs : aDWORD;
activeThreads : integer;
procedure WMCopyData(var wMsg : TWMCopyData); message WM_COPYDATA;
public
cURL : TCheckURL;
end;
...
procedure TmainForm.WMCopyData(var wMsg: TWMCopyData);
var wmData : PCopyDataStruct;
mpURL : pURLs;
begin
wmData:=wMsg.CopyDataStruct;
mpURL:=wmData.lpData;
...
....
cURL.msgWnd:=self.Handle;
hThread:=CreateThread(nil, 0, @CheckURL, @cURL, 0, ThreadID);
if hThread=0 then Header.Lines.Add("No Thread!");
где поток описан как
TCheckURL = record
msgWnd : HWND;
...
end;
pURLs = ^TCheckURL;
function CheckURL(p : pointer) : longint; stdcall;
var cURL : pURLs;
begin
Result:=0;
cURL:=pURLs(p);
...
SendMessage(cURL^.msgWnd, WM_COPYDATA, 0, longint(@wmData));
....
end;
stdcall обязательно.
← →
-=XP=- © (2005-05-28 11:24) [51]Классики не рекомендуют использовать прямую адресацию между потоками.
Потоки одного процесса выполняются в едином адресном пространстве. Поэтому с этим проблем нет.
SendMessage отправляет сообщение не в очередь, а напрямую в оконную процедуру. Поэтому, без синхронизации потоков, эта функция использоваться не может. Для подобного решения можно посоветовать использовать PostMessage.
Но если используется Synchronize(), то приведенный автором вопроса код - совершенно корректный. Зачем в данном случае использовать WinAPI, если можно воспользоваться VCL?
← →
isasa © (2005-05-28 11:30) [52]Немного прокоментирую.
Собственно вызов потокаcURL.msgWnd:=self.Handle; // Это хандлер формы куда передается сообщение
hThread:=CreateThread(nil, 0, @CheckURL, @cURL, 0, ThreadID);
это структура, которая передается потокуTCheckURL = record
msgWnd : HWND;
mainForm: TForm;
...
end;
pURLs = ^TCheckURL;
в нее, например, можно пихнуть все, что угодно, даже TForm.
Но, опять же, напомню прямую адресацию не использовать - дурной тон.
Хотя из потока
mainForm.myControl.Text:="Оба-на!";
работать будет.
← →
isasa © (2005-05-28 11:40) [53]По поводу VCL и потоков см. Ч.Калверта
The WM_COPYDATA message is sent when an application passes data to another application.
Remarks
An application must use the SendMessage function to send this message, not the PostMessage function.
поэтому SendMessage
← →
-=XP=- © (2005-05-28 11:41) [54]Но, опять же, напомню прямую адресацию не использовать - дурной тон.
Я так понимаю, в контексте сказанного Вами, это опечатка?
Объясните, в чем же проявляется "дурной тон" в данном случае?
Какие последствия могут возникнуть в результате прямого обращения к объектам VCL в данном примере (с использованием Synchronize)? Обращение идет в контексте основного потока. Адресное пространство - одно и то же. RTTI присутствует и непротиворечива.
Что Вы имеете в виду, говоря "дурной тон"?
P.S. Напомню, что мы сечас все же говорим о TThread, а не о работе с потоками напрямую через WinAPI.
← →
isasa © (2005-05-28 11:53) [55]Не поленился, нашел.
Ссылка правда старовата , но
Ч.Калверт. Энциклопедия пользователя. стр.134.
пример один к одному,
коментарии
".. главный поток приложения вообще не сможет выполняться, пока не завершится вызов функции Synchronize
← →
-=XP=- © (2005-05-28 12:06) [56]главный поток приложения вообще не сможет выполняться, пока не завершится вызов функции Synchronize
Неверная формулировка.
Главный поток продолжает выполняться. В нем выполняется метод, переданный в качестве аргумента методу Synchronize. Работа метода Synchronize заключается в том, что он передает в главный поток сообщение с указателем на метод, переданный в качестве аргумента, и ожидает окончания обработки этого сообщения, то-есть, вторичный поток останавливается. По факту получения сообщения, главный поток выполняет код переданного в качестве параметра метода в совем собственном контексте. По окончании выполнения этого метода, главный поток продолжает выполняться дальше, и вторичный поток возвращается к своему выполнению.
P.S. Хотя, говорить о том, какой поток останавливается - не совсем корректно. На самом деле, два потока синхронизируются, и выполняется один программный код на двоих. Хотя, все же, я склонен утверждать, что останавливается вторичный поток, отдавая метод на выполнение в контексте главного потока.
← →
isasa © (2005-05-28 12:22) [57]:))))))))
Все претензии к переводчику (П.А.Матлаш гл.1-8)
А если серьезно, в данном случае, проще через API.
По поводу синхронизации.
В данном примере - реакции одного потока на действия другого (исключая главный поток), я не вижу.
← →
-=XP=- © (2005-05-28 12:38) [58]Вот "цитаты" из VCL:
procedure TThread.Synchronize(Method: TThreadMethod);
begin
...
FMethod := Method;
SyncProc.Thread := Self;
SyncList.Add(@SyncProc); // Добавляем наш метод, который мы хотим выполнить в контексте основного потока, в список ("В очередь, сукины дети, в очередь!" (С))
...
WaitForSingleObject(SyncProc.Signal, INFINITE); // И ждем окончания выполнения метода в контексте основного потока ("Ждут, не дождутся, когда ж наши мамы вернуться " (С))
...
end;
procedure TApplication.WndProc(var Message: TMessage);
begin
...
case Message.Msg of
...
WM_NULL: CheckSynchronize; //А вот тут основной поток приступает к обработке запросов от вторичных потоков
...
end;
function CheckSynchronize: Boolean;
begin
...
while SyncList.Count > 0 do // Проходим список потоков, ожидающих выполнения своих методов в контексте основного потока
begin
SyncProc := SyncList[0]; // Берем метод для первого ожидающего потока
SyncList.Delete(0);
...
SyncProc.Thread.FMethod; // А тут и выполнение нашего метода в контексте основного потока
...
SetEvent(SyncProc.signal); // А теперь говорим ожидающему вторичному потоку, что он может продолжить выполнение
end;
...
end;
Я так думаю, к правильности кода из папки Source\VCL претензий нет? :)
А если серьезно, в данном случае, проще через API.
Ну, это кому как. :)
В данном примере - реакции одного потока на действия другого (исключая главный поток), я не вижу
Они синхронизируются через главный поток (см. код, приведенный выше) - то есть, оба становятся в очередь и ждут. В этом и заключается синхронизация.
← →
-=XP=- © (2005-05-28 12:41) [59]P.S. Прошу прощения, в комментариях "Добавляем наш метод", "Берем метод для первого ожидающего потока" допустил ошибки в описании. На самом деле их надо читать как "Добавляем наш поток" и "Берем первый поток из списка ожидающих потоков".
← →
VMcL © (2005-05-28 12:48) [60]>>isasa © (28.05.05 11:17) [50]
>Я пользуюсь функцией CreateThread (и не заморачиваюсь на TThread)
Пользоваться функцией CreateThread некошерно. Следует пользоваться функцией BeginThread.
← →
VMcL © (2005-05-28 12:51) [61]>>-=XP=- © (28.05.05 12:38) [58]
Кстати, так Borland сделал начиная с D6. В D5 было несколько по-другому.
← →
Defunct © (2005-05-28 19:10) [62]Verg © (28.05.05 07:21) [47]
Один:
Addr Launch (from ebx)
Data (from eax)
W
Страницы: 1 2 вся ветка
Текущий архив: 2005.06.14;
Скачать: CL | DM;
Память: 0.59 MB
Время: 0.051 c