Python:应用程序必须等待另一个完成(互斥)

问题描述 投票:0回答:1

我正在创建一个必须一次运行一个的应用程序,因此我尝试根据以下配方创建它: https://code.activestate.com/recipes/474070-creating-a-single-instance-application/

问题是,我需要应用程序等待另一个应用程序完成然后运行。

我尝试过这样的事情:

def __init__(self) -> None:
    while True:
        lastError = 0
        SetLastError(0)
        self.Mutex = CreateMutex(None, False, self.MUTEX_NAME)
        lastError = GetLastError()
        if (lastError != ERROR_ALREADY_EXISTS):
            break
        else:
            print("It's already running... Waiting...")
            time.sleep(5)

def __del__(self) -> None:
    if self.Mutex:
        CloseHandle(self.Mutex)

当我在 VSCode 上以“调试模式”逐行运行此代码时,它可以工作,因为 GetLastError 在第一个进程完成后返回 0。

但是当我像

python app.py
那样运行两次时,第二个进程总是打印“它已经在运行......等待......”

我该如何解决?

python winapi singleton mutex
1个回答
0
投票

这是预期的行为,因为第一个实例的退出不会自动清除应用程序的后续实例中的最后一个错误代码!

为了使其发挥作用,请考虑使用

WaitForSingleObject

import time
from ctypes import windll, byref, c_ulong
from win32event import WaitForSingleObject, WAIT_OBJECT_0, INFINITE
from win32api import GetLastError, SetLastError
from win32con import ERROR_ALREADY_EXISTS
from win32mutex import CreateMutex

class SingleInstanceApplication:
    def __init__(self, mutex_name):
        self.MUTEX_NAME = mutex_name
        self.Mutex = None
        self.ensure_single_instance()

    def ensure_single_instance(self):
        while True:
            SetLastError(0)
            self.Mutex = CreateMutex(None, False, self.MUTEX_NAME)
            lastError = GetLastError()
            if lastError == ERROR_ALREADY_EXISTS:
                print("It's already running... Waiting...")
                # Wait for the mutex to be released
                wait_result = WaitForSingleObject(self.Mutex, INFINITE)
                if wait_result == WAIT_OBJECT_0:
                    # Mutex is released, can proceed
                    print("Previous instance finished, starting now...")
                    break
            else:
                break  # No error, mutex created successfully, proceed

    def __del__(self):
        if self.Mutex:
            windll.kernel32.CloseHandle(self.Mutex)


if __name__ == "__main__":
    app = SingleInstanceApplication("Global\\MySingleInstanceAppMutex")
    # Put Your application logic here
    print("Application running. Press Ctrl+C to exit.")
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("Application exiting.")

© www.soinside.com 2019 - 2024. All rights reserved.