You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mutex.WaitOne()始终返回true,寻求问题排查帮助

问题排查与修复方案

核心问题1:Mutex未实现跨应用互斥

你当前用new Mutex()创建的是本地互斥体,仅对当前进程内的线程生效,完全无法阻止其他应用(进程)获取锁,所以不管多少个应用调用这个方法,WaitOne()都会直接返回true。

要实现跨应用的互斥,必须创建命名全局互斥体,指定一个系统唯一的名称(注意名称不能和系统其他重名),格式为Global\XXX(加Global前缀确保跨Windows会话生效,比如服务和桌面应用之间)。

核心问题2:锁释放逻辑错误

你的finally块里不管有没有成功获取锁,都尝试调用ReleaseMutex()——如果WaitOne()返回false(比如设置了超时后未拿到锁),此时当前线程并没有持有锁,调用ReleaseMutex()会抛出异常(虽然你catch住了,但属于逻辑错误)。正确的做法是用一个标记记录是否成功获取锁,只在拿到锁的情况下释放。

修复后的代码

public static class BLStaticTask 
{
    // 创建全局命名互斥体,确保跨应用生效
    private static readonly Mutex TasksMut = new Mutex(false, @"Global\Unique_Task_Handling_Mutex"); 

    public static List<Tasks> GetTasksToHandle()
    {
        bool hasLock = false;
        try
        {
            // 可以设置超时时间,比如5000毫秒,避免无限等待
            hasLock = TasksMut.WaitOne(5000);
            if (hasLock)
            {
                using (DBContext db = new DBContext())
                {
                    return db.prGetTasksToHandle().ToList();
                }
            }
            else
            {
                // 超时未获取到锁,返回null或空列表
                return null;
            }
        }
        catch
        {
            return null;
        }
        finally
        {
            // 仅当成功获取锁时,才释放
            if (hasLock)
            {
                try
                {
                    TasksMut.ReleaseMutex();
                }
                catch
                {
                    // 处理释放异常,比如日志记录
                }
            }
        }
    }
}

额外注意事项

  • 命名互斥体的名称要确保唯一,建议用公司或项目前缀避免冲突。
  • 如果是在非管理员权限的应用中使用Global\前缀,可能需要权限设置,也可以用Local\前缀(仅当前用户会话内跨进程生效)。
  • 记得添加超时时间,避免线程无限阻塞在WaitOne()上。

内容的提问来源于stack exchange,提问作者Avihay Hatav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 00:31:02