Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.08.13;
Скачать: CL | DM;

Вниз

Мьютексы в потоке   Найти похожие ветки 

 
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;

ну что ж.. можно конечно, но как-то не очень.


 
Eraser ©   (2006-06-29 00:16) [41]

> [39] Sam Stone ©   (29.06.06 00:14)


> Основной поток не видит мьютексы в "доп" потоках?

видит, ну лучше почитать Рихтера, там все очень понятно и на примерох разьясняется, такие вопросы отпадут сами собой.

> Я пойду учить потоки

вот с этого и надо было начинать :)


 
Sam Stone ©   (2006-06-29 00:20) [42]

Что ж, спасибо, поищу книгу, попробую осилить ;-) Спасибо )


 
Eraser ©   (2006-06-29 00:21) [43]

> [42] Sam Stone ©   (29.06.06 00:20)


> поищу книгу

тут есть http://rouse.front.ru/


 
Sam Stone ©   (2006-06-29 00:26) [44]

Еще раз спасибо )

ЗЫ
пошел в яндекс - нашел вот это: http://www.delphimaster.ru/cgi-bin/nuts.pl?showpage=6 :)))



Страницы: 1 2 вся ветка

Текущий архив: 2006.08.13;
Скачать: CL | DM;

Наверх




Память: 0.59 MB
Время: 0.053 c
2-1153733496
Mintos
2006-07-24 13:31
2006.08.13
Закрыть QuickReport


15-1153094770
Ketmar
2006-07-17 04:06
2006.08.13
никому не нужен удалёный программист?


3-1149574262
Быстрый Шу
2006-06-06 10:11
2006.08.13
Подстановка параметров в TQuery


2-1153673281
Каг Дила?
2006-07-23 20:48
2006.08.13
У меня какие-то пробелемы компонентом


2-1153752165
VALUA
2006-07-24 18:42
2006.08.13
DBGrid - N колонки