Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
2-1153487778
bajenovv
2006-07-21 17:16
2006.08.13
кнопка


2-1153699751
Mr.Grey
2006-07-24 04:09
2006.08.13
Динамическое создание формы


15-1151925090
Stanislav
2006-07-03 15:11
2006.08.13
Авторизация на сайте


15-1153287680
KygECHuK
2006-07-19 09:41
2006.08.13
Где найти словар?


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





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский