在Python(win32)中等待互斥锁创建

2 投票
2 回答
3007 浏览
提问于 2025-04-17 19:45

我正在使用win32event这个Python模块来和另一个程序(基于C#)创建的互斥量(Mutex)进行交互。

我的代码是打开一个互斥量,然后在上面等待:

hWait = win32event.OpenMutex(win32con.MUTEX_ALL_ACCESS, False, "mutexname")
win32event.WaitForSingleObject(hWait, 20000)

这段代码的问题在于,如果互斥量还没有被创建(比如说,如果Python程序在C#程序创建它之前就尝试打开它),那么代码就会失败。

我该如何阻止程序继续运行,直到互斥量被创建?有没有什么Python的方法或者库可以做到这一点?

2 个回答

0

注意,当使用 win32event.WaitForSingleObject 时,不一定要指定一个任意但足够长的等待时间(比如20000毫秒),你也可以直接使用 win32event.INFINITE,这样就会一直等待,直到某个事件发生,示例如下:

win32event.WaitForSingleObject(waitable, win32event.INFINITE)

这在某些情况下很有用,比如你需要告诉另一个线程,互斥量(mutex)已经打开了。

因为如果互斥量还没有创建,等待它是会失败的,所以我们创建一个事件,当互斥量打开时触发这个事件。

mutex_open = win32event.CreateEvent(None, 0, 0, None)

然后启动一个线程来等待这个事件:

def wait_for_opening(open_evt):
   win32event.WaitForSingleObject(open_evt, win32event.INFINITE)
   print("Got notified that mutex is now open.")

waiter = threading.Thread(target=wait_for_opening, args=(mutex_open,))
waiter.start()

为了模拟另一个程序,启动另一个线程,在过一段时间后创建互斥量:

def delayed_create():
   time.sleep(1)
   m = CreateMutex(None, True, u"mutexname")

creator = threading.Thread(target=delayed_create)
creator.start()

最后,运行一个循环,等待互斥量打开,并在打开后设置事件。

while True:

   try:
      hWait = win32event.OpenMutex(MUTEX_ALL_ACCESS, False, "mutexname")
   except pywintypes.error:
      pass
   else:
      win32event.SetEvent(mutex_open)
      break

注意 setEvent 的调用。

所以,当运行这段代码时,过一段时间后,waiter 线程会收到通知,知道互斥量现在已经打开了。

0

正如@manuell在评论中提到的,简单的解决办法是不断循环,直到互斥锁被创建,同时默默地捕捉当互斥锁还不存在时出现的错误:

while True:

   try:
      hWait = win32event.OpenMutex(MUTEX_ALL_ACCESS, False, "mutexname")
   except pywintypes.error:
      pass
   else:
      break

根据你的具体情况,你可能想在循环中明确地让程序暂停一会儿,或者把这个等待的循环放到一个单独的线程中,或者把它变成一个生成器或协程,甚至可以用它来触发一个win32事件,以便在另一个已经运行的线程中执行某些操作(你可以看看我其他的回答,了解如何等待一个事件直到它发生)。

撰写回答