我有一个公共资源,我想要1,只有我的应用程序的一个实例(或它的COM API)可以随时访问。我曾尝试使用互斥锁保护此资源,但是当主机dotnet应用程序的多个线程尝试访问COM对象时,似乎没有释放互斥锁。这是我用来保护资源的代码。
repeat
Mutex := CreateMutex(nil, True, PChar('Connections'));
until (Mutex <> 0) and (GetLastError <> ERROR_ALREADY_EXISTS);
try
//use resource here!
finally
CloseHandle(Mutex);
end;
如果我同时运行线程,第一个线程就会通过(显然是第一个创建互斥锁的线程),但后续线程会在重复循环中被捕获。如果我以5秒的间隔运行每个线程,那么一切都没问题。
我怀疑我在这里没有正确使用互斥锁,但我发现很少有关于如何执行此操作的文档。
有什么想法吗?
答案 0 :(得分:15)
您使用的互斥锁是错误的。您应该等待它并释放它,而不是不断重新创建它。
初始化期间:
Mutex := CreateMutex(nil, False, 'Connections');
if Mutex = 0 then
RaiseLastOSError;
当您想要访问资源时
if WaitForSingleObject(Mutex, INFINITE) <> WAIT_OBJECT_0 then
RaiseLastOSError;
try
// Use resource here
finally
ReleaseMutex(Mutex)
end;
在定稿期间
CloseHandle(Mutex);
此外,由于互斥锁是全局的,因此您应该选择比名称的“连接”更独特的东西。我们在我们的末尾添加了一个GUID。
答案 1 :(得分:11)
尝试使用这个简单的演示代码。启动应用程序的多个实例,您可以从背景颜色中看到它们如何共享互斥锁:
procedure TForm1.FormCreate(Sender: TObject);
begin
fMutex := SyncObjs.TMutex.Create(nil, False, 'GlobalUniqueName');
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
fMutex.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Color := clRed;
Update;
fMutex.Acquire;
try
Color := clGreen;
Update;
Sleep(5 * 1000);
finally
fMutex.Release;
end;
Color := clBtnFace;
end;
请注意,我选择使用TMutex
单元中的SyncObjs
类,这简化了事情。