Форум: "Основная";
Текущий архив: 2006.08.13;
Скачать: [xml.tar.bz2];
ВнизМьютексы в потоке Найти похожие ветки
← →
Sam Stone © (2006-06-28 22:25) [0]Доброго времени суток.
Как создать мьютекс в потоке (TThread) так, чтобы потом в основном потоке программы можно было проверить создан он или нет? Просто CreateMutex с тем же именем ни к чему не приводит :(
← →
Fay © (2006-06-28 22:26) [1]> Просто CreateMutex с тем же именем ни к чему не приводит :(
В смысле? К чему не приводит?
← →
Sam Stone © (2006-06-28 22:37) [2]Если повторно создать мьютекс с тем же именем GetLastError вернет ошибку ERROR_ALREADY_EXISTS. Этого не происходит.
← →
Leonid Troyanovsky © (2006-06-28 22:50) [3]
> Sam Stone © (28.06.06 22:25)
> Как создать мьютекс в потоке (TThread) так, чтобы потом
> в основном потоке программы можно было проверить создан
> он или нет?
Попробую описать решение проблемы так, как она обычно
встречается в жизни. Т.е., основной поток создает мьютекс
и передает его хендл вторичному. В этом случае, у вторичного
потока нет нужды сомневаться в валидности оного.
Ну, а если нужда возникла, то у него есть еще в запасе
DuplicateHandle.
С другой стороны, что-то мне подсказывает, что на месте
мьютекса мог быть и Event (CreateEvent).
--
Regards, LVT.
← →
Fay © (2006-06-28 22:57) [4]2 Sam Stone © (28.06.06 22:37) [2]
function Jopa(Parameter : Pointer) : Integer;
begin
CreateMutex(nil, True, "JOPA");
end;
procedure TForm1.Button1Click(Sender : TObject);
var
dw : DWORD;
begin
CloseHandle(BeginThread(nil, 0, Jopa, nil, 0, dw));
Sleep(100);
CreateMutex(nil, True, "JOPA");
RaiseLastOSError;
end;
← →
Leonid Troyanovsky © (2006-06-28 23:01) [5]
> Sam Stone © (28.06.06 22:37) [2]
> Если повторно создать мьютекс с тем же именем GetLastError
> вернет ошибку ERROR_ALREADY_EXISTS. Этого не происходит.
А что возвращает сама CreateMutex?
--
Regards, LVT.
← →
Eraser © (2006-06-28 23:09) [6]> [0] Sam Stone © (28.06.06 22:25)
> Как создать мьютекс в потоке (TThread) так, чтобы потом
> в основном потоке программы можно было проверить создан
> он или нет? Просто CreateMutex с тем же именем ни к чему
> не приводит :(
в общем случае необходимо создавать мьютекс в основном (управляющем) потоке, если к нему может иметь доступ как основной поток, так и дополнительный (или несколько дополнительных), и при этом у главного потока нет возможности напрямую обратиться к полю экземпляра объекта доп. потока.
← →
Sam Stone © (2006-06-28 23:12) [7]>> А что возвращает сама CreateMutex?
хэндл.
>> Fay © (28.06.06 22:57) [4]
TMyThread = class(TThread)
procedure Execute;overload;
end;
...
procedure TMyThread.Execute;
begin
CreateMutex(nil,true,"aaa");
if GetLastError=ERROR_ALREADY_EXISTS then showmessage("asd");
end;
...
procedure TForm1.Button1Click();
var t:TMyThread;
begin
...
CreateMutex(nil,true,"aaa");
t:=TMyThread.create(false);
...
end;
Не матерится.
← →
Eraser © (2006-06-28 23:14) [8]> [7] Sam Stone © (28.06.06 23:12)
> Не матерится.
странно что не патерится. ;-)
← →
Eraser © (2006-06-28 23:14) [9]> патерится
п := м;
← →
Fay © (2006-06-28 23:16) [10]> showmessage("asd");
Какой ещё нафиг showmessage?
← →
Fay © (2006-06-28 23:17) [11]2 Leonid Troyanovsky © (28.06.06 22:50) [3]
А зачем DuplicateHandle? Я не понял...
← →
Leonid Troyanovsky © (2006-06-28 23:20) [12]
> Sam Stone © (28.06.06 23:12) [7]
> >> А что возвращает сама CreateMutex?
> хэндл.
Кто б мог подумать.
"Что" может означать лишь значение.
Иначе, за кого ты нас принимаешь? :)
> CreateMutex(nil,true,"aaa");
> if GetLastError=ERROR_ALREADY_EXISTS then showmessage("asd");
Дык вот, проверять оное имеет смысл, если возвращаемое
CreateMutex <> 0
Ну, а далее посмотрим.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2006-06-28 23:22) [13]
> Fay © (28.06.06 23:17) [11]
> А зачем DuplicateHandle? Я не понял...
Если приобретателю хендла важна его валидность,
то без оного трудно обойтись.
--
Regards, LVT.
← →
Sam Stone © (2006-06-28 23:24) [14]Leonid Troyanovsky © (28.06.06 23:20) [12]
смотрел примеры запрета запуска второй копии приложения, там таким макаром реализовано.
Возможно надо будет с утра пересмотреть ;)
Fay © (28.06.06 23:16) [10]
надо же как-то ругнуться.
в любом случае запускал процесс длительный, в котором создавал в начале мьютекс, который зарубался в конце работы, а в основном потоке после этого пытался создать с тем же именем (глуповатый пример ожидания завершения работы потока) - создавался и все пролетало.
← →
Fay © (2006-06-28 23:26) [15]2 Leonid Troyanovsky © (28.06.06 23:22) [13]
А это имеет смысл в рамках одного процесса?
Я не понимаю ...
← →
Leonid Troyanovsky © (2006-06-28 23:37) [16]
> Fay © (28.06.06 23:26) [15]
> А это имеет смысл в рамках одного процесса?
Пуркуа бы не нет?
Изловчившийся сохранить значение хендла в своей локальной переменной
вторичный поток будет застрахован от самодурства первичного.
--
Regards, LVT.
← →
Fay © (2006-06-28 23:37) [17]2 Sam Stone © (28.06.06 23:24) [14]
> надо же как-то ругнуться.
Ладно, Гейтс тебе судья. А брякпойнт после then не пробовал ставить?
← →
Fay © (2006-06-28 23:38) [18]2 Leonid Troyanovsky © (28.06.06 23:37) [16]
Самодурство - это CloseHandle?
← →
Leonid Troyanovsky © (2006-06-28 23:41) [19]
> Sam Stone © (28.06.06 23:24) [14]
> смотрел примеры запрета запуска второй копии приложения,
> там таким макаром реализовано.
Таких примеров море.
> Возможно надо будет с утра пересмотреть ;)
Тогда, следует смотреть лишь лучшие.
--
Regards, LVT.
← →
Sam Stone © (2006-06-28 23:44) [20]Fay © (28.06.06 23:37) [17]
Пробовал. Запутался окончательно :) Значит пора спать :))
тогда такой код:
тот же execute
procedure TMythead.execute;
begin
createmutex(nil,true,"aaa");
sleep(5000);
Terminate;
end;
procedure TForm1.Button1click;
var q:TMyThread;
begin
//вариант 1
q:=TMyThread.create(false);
CreateMutex(nil,true,"aaa");
while GetLastError=ERROR_ALREADY_EXISTS do
CreateMutex(nil,true,"aaa");
halt;
//вылетает сразу
//вариант 2
q:=TMyThread.create(false);
while not q.terminated do;
halt;
//добросовесно ждет
end;
Вопрос: чего я тут не понимаю? :)
← →
Leonid Troyanovsky © (2006-06-28 23:44) [21]
> Fay © (28.06.06 23:38) [18]
> Самодурство - это CloseHandle?
Можно также представить изменение глобальной переменной,
на которую рассчитывал вторичный поток.
--
Regards, LVT.
← →
Fay © (2006-06-28 23:46) [22]2 Leonid Troyanovsky © (28.06.06 23:44) [21]
Леонид, это уже фашизм.
Никто не мешает дубликату быть глобальной переменной 8))
← →
Eraser © (2006-06-28 23:48) [23]> [14] Sam Stone © (28.06.06 23:24)
> надо же как-то ругнуться.
обращаться из доп. потока к VCL недопустимо, лучше уж тогда использовать Windows.MessageBox, хотя я вообще противник диалога с пользователем из доп. потоков.
> в любом случае запускал процесс длительный, в котором создавал
> в начале мьютекс, который зарубался в конце работы, а в
> основном потоке после этого пытался создать с тем же именем
> (глуповатый пример ожидания завершения работы потока) -
> создавался и все пролетало.
как-то непонятно объяснил )
← →
Fay © (2006-06-28 23:50) [24]2 Sam Stone © (28.06.06 23:44) [20]
Terminate в TMythead.execute явно лишнийwhile GetLastError=ERROR_ALREADY_EXISTS do
CreateMutex(nil,true,"aaa");
LOL
Спокойной ночи 8)
← →
Sam Stone © (2006-06-28 23:50) [25]>Eraser © (28.06.06 23:48) [23]
см [20]
← →
Eraser © (2006-06-28 23:50) [26]> [20] Sam Stone © (28.06.06 23:44)
вот сразу бы так и сказал ))
procedure TForm1.Button1click;
var
q: TMyThread;
begin
q := TMyThread.create(false);
q.WaitFor;
q.Free;
end;
← →
Sam Stone © (2006-06-28 23:57) [27]> Eraser © (28.06.06 23:50) [26]
q.WaitFor, как я понимаю, вместо дури While GetLastError... ?
> Fay © (28.06.06 23:50) [24]
Не понял насмешки. Перед while еще один createmutex, GetLastError будет с него начинать. Или я не прав?
← →
Leonid Troyanovsky © (2006-06-28 23:58) [28]
> Fay © (28.06.06 23:46) [22]
> Никто не мешает дубликату быть глобальной переменной 8))
Если все поткоки разрабатывались в рамках одного приложения,
то, проблем, видимо, быть не должно (в смысле организации
хранения валидной ссылки).
Однако, в любом случае, если некоему потоку удалось
DuplicateHandle, то, далее, он может быть спокоен относительно
дальнйших планов всех остальных.
--
Regards, LVT.
← →
Eraser © (2006-06-28 23:59) [29]> [27] Sam Stone © (28.06.06 23:57)
> q.WaitFor, как я понимаю, вместо дури While GetLastError...
> ?
именно, хотя и делает бесполезным использование доп. потока.
> Не понял насмешки. Перед while еще один createmutex, GetLastError
> будет с него начинать. Или я не прав?
какая конкретно задача?
← →
Sam Stone © (2006-06-29 00:00) [30]Тьфу, не дописал...
> Eraser © (28.06.06 23:50) [26]
>> [20] Sam Stone © (28.06.06 23:44)
> вот сразу бы так и сказал ))
Собсно интересует в чем НЕработоспособность [20].
← →
Eraser © (2006-06-29 00:01) [31]> [20] Sam Stone © (28.06.06 23:44)
в том, что:
1. убого.
2. скорее всего будет кушать 99.5% процессорного времени.
← →
Sam Stone © (2006-06-29 00:03) [32]> Eraser © (28.06.06 23:59) [29]
задача - подождать пока отработает код в потоке(не я его туда заносил и вынимать не надо) и после зарубить программу. Честно говоря, про WaitFor не знал :(
Просто попробовал "пощупать" мьютексы, заинтересовало в чем косяк.
← →
Fay © (2006-06-29 00:05) [33]2 Leonid Troyanovsky © (28.06.06 23:58) [28]
ОК, понял
2 Sam Stone © (28.06.06 23:57) [27]
Перефразируем.купить_бутылку_водки(0.75, 40, "Смирнофф");
...
купить_бутылку_водки(0.5, 40, "Смирнофф");
while ПроверитьХолодильник() = ВОДКА_УЖЕ_ЕСТЬ do
купить_бутылку_водки(0.5, 40, "Смирнофф");
Денюшек может не хватить
← →
Sam Stone © (2006-06-29 00:05) [34]> Eraser © (29.06.06 00:01) [31]
Ну туда можно, например, Application.processmessages сунуть, чтоб и проц не отъедало от выполнения основной задачи, и окно программы не "зависало".
← →
Eraser © (2006-06-29 00:07) [35]> [32] Sam Stone © (29.06.06 00:03)
> задача - подождать пока отработает код в потоке(не я его
> туда заносил и вынимать не надо) и после зарубить программу.
если программа не консольная, все таки не очень хорошо, если она будет подвисать на довольно большой промежуток времени, поэтому советую работать с доп. потоком асинхронно, а не дожидаться его завершения, усыпляя основной поток.
← →
Fay © (2006-06-29 00:08) [36]2 Sam Stone © (29.06.06 0:05) [34]
> Application.processmessages сунуть, чтоб и проц не отъедало
Ложитесь спать
← →
Sam Stone © (2006-06-29 00:08) [37]> Fay © (29.06.06 00:05) [33]
Правильно, зациклились. Почему тогда программа завершилась СРАЗУ же по halt? Для "правильности" можно в конце работы потока ReleaseMutex добавить.
← →
Eraser © (2006-06-29 00:10) [38]> [37] Sam Stone © (29.06.06 00:08)
да при чем тут вообще мьютексы? дескриптор потока сам по себе может выступать объектом синхронизации!
← →
Sam Stone © (2006-06-29 00:14) [39]> Eraser © (29.06.06 00:10) [38]
абсолютно не причем. Вот кольнуло мне. А теперь интесно - в чем именно косяк. Основной поток не видит мьютексы в "доп" потоках? Если не хотите отвечать можно свернуть разговор. Я пойду учить потоки и радоваться WaitFor"ру.
← →
Eraser © (2006-06-29 00:14) [40]> Ну туда можно, например, Application.processmessages сунуть
while not q.terminated do
begin
Application.ProcessMessages;
Sleep(1);
end;
q.Free;
halt;
ну что ж.. можно конечно, но как-то не очень.
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2006.08.13;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.031 c