互斥体未释放

2023-12-08

我的 c# WinForm 解决方案包含多个项目,其中包括包含 frmAdmin 的管理项目和包含 frmUser 的用户项目。第三个项目包含 frmTimer,它有一个定期启动 frmUser 的计时器。

我希望 frmTimer 在 frmAdmin 打开时不启动 frmUser。

我使用命名互斥体来告诉 frmTimer frmAdmin 是否打开;但是,在 frmAdmin 关闭后,互斥体似乎不会被释放。

互斥体是在 frmAdmin 中使用如下代码创建的:

public partial class frmAdmin : Form
{
    Mutex m;
    protected override void OnShown(EventArgs e)
    {
        base.OnShown(e);
        m = new Mutex(true, "frmAdmin");
    }
    protected override void OnClosed(EventArgs e)
    {
        base.OnClosed(e);
        m.ReleaseMutex();
        MessageBox.Show("Debug 1 -- In the frmAdmin ONCLOSED Event.");  //test code
        Debug.WriteLine("Debug 1 -- In the frmAdmin ONCLOSED Event.");  //test code
  }

    public frmAdmin(string strPassedFromLogin)
    {
        InitializeComponent();
        <<Code snipped>>
             }

    private void frmAdmin_FormClosing(object sender, FormClosingEventArgs e)
    {
        //Start _ Added
        bool mutexSet = true;
        try
        {
            Mutex.OpenExisting("frmAdmin");
            MessageBox.Show("Debug 2 -- In the frmAdmin FORMCLOSING Event.");  //test code
        }
        catch (WaitHandleCannotBeOpenedException)
        {
            mutexSet = false;
        }
        if (mutexSet)
        {
            base.OnClosed(e);
            m.ReleaseMutex();
        }
        //End _ Added

        Application.Exit();
    }

    <<Code snipped>>
}

最初,我在 frmAdmin_FormClosing 方法中没有任何互斥代码(该方法仅包含 Application.Exit() 行)。我添加了互斥体代码试图释放互斥体,但它仍然没有被释放。

互斥锁在 frmTimer 中的使用如下:

    private void tmTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        bool adminIsOpen = true;
        try
        {
            Mutex.OpenExisting("frmAdmin");
            MessageBox.Show("Debug 3 -- Mutex exists: frmAdmin IS open.");  //test code
        }
        catch (WaitHandleCannotBeOpenedException)
        {
            adminIsOpen = false;
            MessageBox.Show("Debug 4 -- Mutex doesn't exists: frmAdmin is NOT open.");  //test code
        }

        if (adminIsOpen == false)
        {
          //frmAdmin is closed; go ahead and open frmUser.
            <<Code snipped>>
        }
    }

当我运行应用程序时,每次计时器触发时都会出现带有“调试 4”文本的消息框,直到我打开 frmAdmin(密码验证后从 frmLogin 启动 frmAdmin),从那时起,每次都会出现带有“调试 3”文本的消息框计时器触发的时间,即使在我退出 frmAdmin 后也是如此。退出 frmAdmin 时,我看到带有“调试 2”文本的消息框。我从未见过带有“调试 1”文本的消息框(或输出窗口消息)。

看起来好像在 frmAdmin 关闭后互斥体没有释放,这会阻止 frmUser 启动。

任何帮助表示赞赏。

这是一个后续问题this问题。

UPDATE

这是我让它工作后的代码。我之所以能成功,是因为 Hans Passant 和 Chris Taylor 以及 Serhio 的回答this post.

现在,互斥锁已在 frmAdmin 中创建,代码如下:

    Mutex m;
    protected override void OnShown(EventArgs e)
    {
        base.OnShown(e);
        m = new Mutex(true, "frmAdmin");
    }

    //This 'OnClosed' event is skipped when this application is terminated using only Exit(); therefore, call Close() before calling Exit().
    //The 'catch' code is added to insure the program keeps running in the event these exceptions occur.
    protected override void OnClosed(EventArgs e)
    {
        if (m != null)
        {
            try
            {
                base.OnClosed(e);
                m.ReleaseMutex();
                m.Close(); 
            }
            catch (AbandonedMutexException)
            {
                //This catch is included to insure the program keeps running in the event this exception occurs.
            }
            catch (ApplicationException)
            {
                //This catch is included to insure the program keeps running in the event this exception occurs.
            }
            catch (SynchronizationLockException)
            {
                //This catch is included to insure the program keeps running in the event this exception occurs.
            }
        }
    }

互斥锁在 frmTimer 中的使用如下:

private void tmTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    bool adminIsOpen = false;
    Mutex _muty = null;
    try
     {
        //If the named mutex does not exist then OpenExisting will throw the 'WaitHandleCannotBeOpenedException',
        //otherwise the mutex exists and Admin is open.
        _muty = Mutex.OpenExisting("frmAdmin");
        adminIsOpen = true;
        _muty.Close();
    }
    catch (WaitHandleCannotBeOpenedException)
    {
        //This catch is thrown when Admin is not opened (keep 'adminIsOpen = false'). Do not delete this catch.
    }
    catch (AbandonedMutexException)
    {
        //This catch is included to insure the program keeps running in the event this exception occurs.
    }

    if (adminIsOpen == false)
    {
        //frmAdmin is closed; go ahead and open frmUser.
        <<Code snipped>>
    }
}

问题出在 Elapsed 事件处理程序中,它检查互斥体是否exists使用 Mutex.OpenExisting()。当然它存在。您实际上并没有检查它是否已发出信号。这需要调用其 WaitOne(0) 方法。

另请注意,在 Timer.Elapsed 事件中创建表单是非常不合适的。该事件运行一个线程池线程,它根本不适合充当 UI 线程。它具有错误的 COM 状态([STAThread] 和 Thread.SetApartmentState),这是您无法在线程池线程上更改的属性。请改用常规 Form.Timer,以便在程序的 UI 线程上创建表单。

编辑:还要注意不可避免的竞争,计时器可以在一微秒内创建用户before管理表单关闭。换句话说,您将拥有一个没有管理员表单的用户表单,这是您编写此代码要防止的一个情况。这样合适吗?尝试不同进程中的表单相互影响是一个坏主意......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

互斥体未释放 的相关文章

  • 如何创建可以像 UserControl 一样编辑的 TabPage 子类?

    我想创建一个包含一些控件的 TabPage 子类 并且我想通过设计器来控制这些控件的布局和属性 但是 如果我在设计器中打开子类 我将无法像在 UserControl 上那样定位它们 我不想创建一个带有 UserControl 实例的 Tab
  • 为什么要序列化对象需要 Serialized 属性

    根据我的理解 SerializedAttribute 不提供编译时检查 因为它都是在运行时完成的 如果是这样 那么为什么需要将类标记为可序列化呢 难道序列化器不能尝试序列化一个对象然后失败吗 这不就是它现在所做的吗 当某些东西被标记时 它会
  • 如何使用recv()检测客户端是否仍然连接(并且没有挂起)?

    我写了一个多客户端服务器程序C on SuSE Linux 企业服务器 12 3 x86 64 我为每个客户端使用一个线程来接收数据 我的问题是 我使用一个终端来运行服务器 并使用其他几个终端来运行服务器telnet到我的服务器 作为客户端
  • C++ 异步线程同时运行

    我是 C 11 中线程的新手 我有两个线程 我想让它们同时启动 我可以想到两种方法 如下 然而 似乎它们都没有按照我的预期工作 他们在启动另一个线程之前启动一个线程 任何提示将不胜感激 另一个问题是我正在研究线程队列 所以我会有两个消费者和
  • 如何配置 WebService 返回 ArrayList 而不是 Array?

    我有一个在 jax ws 上实现的 java Web 服务 此 Web 服务返回用户的通用列表 它运行得很好 Stateless name AdminToolSessionEJB RemoteBinding jndiBinding Admi
  • IronPython:没有名为 json 的模块

    我安装了 IronPython 我的 python 文件如下所示 import sys print sys version import json 运行它的代码 var p Python CreateEngine var scope p C
  • 当前的 c++ 工作草案与当前标准有何不同

    通过搜索该标准的 PDF 版本 我最终找到了这个链接C 标准措辞草案 http www open std org jtc1 sc22 wg21 docs papers 2012 n3376 pdf从 2011 年开始 我意识到我可以购买最终
  • 生产代码中的 LRU 实现

    我有一些 C 代码 需要使用 LRU 技术实现缓存替换 目前我知道两种实现LRU缓存替换的方法 每次访问缓存数据时使用时间戳 最后比较替换时的时间戳 使用缓存项的堆栈 如果最近访问过它们 则将它们移动到顶部 因此最后底部将包含 LRU 候选
  • 当“int”处于最大值并使用 postfix ++ 进行测试时,代码定义良好吗?

    示例 未定义行为的一个示例是整数溢出的行为 C11dr 3 4 3 3 int溢出是未定义的行为 但这是否适用于存在循环的以下内容 并且不使用现在超出范围的副作用i 特别是 这是否后缀增量规格帮助 结果的值计算在副作用之前排序 更新操作数的
  • 当模板类不包含可用的成员函数时,如何在编译时验证模板参数?

    我有以下模板struct template
  • 获取 2 个数据集 c# 中的差异

    我正在编写一个简短的算法 它必须比较两个数据集 以便可以进一步处理两者之间的差异 我尝试通过合并这两个数据集并将结果更改放入新的数据集来实现此目标 我的方法如下所示 private DataSet ComputateDiff DataSet
  • g++ 对于看似不相关的变量“警告:迭代...调用未定义的行为”

    考虑以下代码strange cpp include
  • 有没有一种简单的方法可以让 Visual Studio 2015 使用特定的 ToolsVersion?

    使用特定版本构建项目或解决方案时msbuild我可以使用以下命令选择早期的 net 工具链 toolsversion or tv switch C Program Files x86 MSBuild 14 0 bin msbuild tv
  • 耐用功能是否适合大量活动?

    我有一个场景 需要计算 500k 活动 都是小算盘 由于限制 我只能同时计算 30 个 想象一下下面的简单示例 FunctionName Crawl public static async Task
  • 结构体指针的动态数组

    我必须使用以下代码块来完成学校作业 严格不进行任何修改 typedef struct char firstName char lastName int id float mark pStudentRecord pStudentRecord
  • 使用 C# 从 DateTime 获取日期

    愚蠢的问题 给定日期时间中的日期 我知道它是星期二 例如我如何知道它的 tue 2 和 mon 1 等 Thanks 您正在寻找星期几 http msdn microsoft com en us library system datetim
  • 双精度类型二维多维数组的 pinvoke 编组作为 c# 和 c++ 之间的输入和输出

    我有以下我正在尝试解决的双物质类型的 2d 多维数组的 c 和 c pinvoke 编组 我已经查看了以下热门内容以获得我目前拥有的内容使用双精度数组进行 P Invoke 在 C 和 C 之间编组数据 https stackoverflo
  • WinRT 定时注销

    我正在开发一个 WinRT 应用程序 要求之一是应用程序应具有 定时注销 功能 这意味着在任何屏幕上 如果应用程序空闲了 10 分钟 应用程序应该注销并导航回主屏幕 显然 执行此操作的强力方法是在每个页面的每个网格上连接指针按下事件 并在触
  • Googletest:如何异步运行测试?

    考虑到一个包含数千个测试的大型项目 其中一些测试需要几分钟才能完成 如果按顺序执行 整套测试需要一个多小时才能完成 通过并行执行测试可以减少测试时间 据我所知 没有办法直接从 googletest mock 做到这一点 就像 async选项
  • 使用 Crypto++ 获取 ECDSA 签名

    我必须使用 Crypto 在变量中获取 ECDSA 签名 我在启动 SignMessage 后尝试获取它 但签名为空 我怎样才能得到它 你看过 Crypto wiki 吗 上面有很多东西椭圆曲线数字签名算法 http www cryptop

随机推荐

  • pandas - groupby 和重新缩放值

    我想向此数据框添加一个重新缩放的列 I Value A 1 A 4 A 2 A 5 B 1 B 2 B 1 这样新列 我们称之为scale 遵循一个函数value每组的列I 该函数只是每个组范围的标准化 lambda x x min x m
  • 如何在单个 MSI 中部署多个项目?

    我的解决方案中有 3 个要部署的项目 是否有一种快速有效的方法可以使用 Visual Studio 的安装项目来使用一个 MSI 部署所有三个应用程序 并让用户在安装过程中决定要安装哪些应用程序 我有 3 个单独应用程序的设置项目 我还有一
  • Google 表格中的一项功能可处理多个工作表

    在 Google Sheets 中我必须重复一个函数 因为getSheetByName 不接受一系列工作表 它只接受一张工作表 有没有一种方法可以让一个函数循环指定的工作表 不是所有工作表 i e 表 1 表 2 等 function re
  • 蓝牙SPP接收到的一些包帧会丢失还是?

    我使用android示例代码进行修改 只想收到包裹 但是 我的代码只在这里修改 private final Handler mHandler new Handler Override public void handleMessage Me
  • 在 grails 的 jasper 报告中以 pdf 格式显示新安装的字体

    我正在使用 iReport 4 5 0 和 grails 2 1 1 我想对 pdf 格式的报告中的某些文本使用 Canterbury 字体 因此我使用 iReport 设计器将该字体分配给我想要的文本 我还进入 iReport 设计器的工
  • 熟悉 MVC - 如何使用会话逻辑、附加类和后台逻辑

    在编写 PHP 代码时 我决定放弃意大利面条式代码并尝试实现 MVC 为了实现MVC框架 我发泄本文文章给了我一个良好的开端 我成功地创建了我的网站并开发了前端 现在 我正在尝试使用会话和其他会员区功能来实现后端 我的大脑充满了新信息 我的
  • 查找两个字符串数组之间的非公共元素

    有一个问题是如何找到两个字符串数组之间的非公共元素 例如 String a a b c d String b b c O p should be a d 我已经尝试过以下方法 但请告知是否有其他有效的方法来实现相同的目标 String a
  • TLabel 和 TGroupbox 标题在调整大小时闪烁

    所以 我有一个应用程序加载不同的插件并创建一个 每个 TPageControl 上都有一个新选项卡 每个 DLL 都有一个与其关联的 TForm 创建表单时将其父级 hWnd 作为新的 TTabSheet 由于就 VCL 而言 TTabSh
  • WebResource.axd 不适用于 Internet Explorer 11

    我们正在针对新的 Windows 8 1 IE 11 浏览器 classic 和 Metro 测试我们的网站 有一个Javascript文件嵌入WebResource axd The WebResource可以在 Firefox Googl
  • 将 H2 数据传输到 PostgreSQL

    我正在从 H2 数据库过渡到 PostgreSQL 据我发现 在 H2 上执行 SCRIPT TO 命令时创建的 SQL 转储包含几个不适当的结构 Unicode 数据用函数 STRINGDECODE unicode data 包装 二进制
  • 将OutputStream发送到浏览器并让浏览器保存它[重复]

    这个问题在这里已经有答案了 我想从 Rich Faces 数据表导出数据 我已经从数据表中的数据创建了outputStream 现在想将这个OutputStream发送到浏览器并让它保存 我怎样才能做到这一点 FileOutputStrea
  • 无法在无 cookie Web 应用程序上创建 asp.net 会话

    我有一个无cookie的基于asp net 4 5的网络应用程序
  • HTML5 localStorage 不适用于 Android WebView

    我正在使用 Buzztouch 为客户端制作移动应用程序 因此 html 页面不在应用程序内 它们是通过 JSON 从服务器加载的 客户希望应用程序上有一个屏幕 用户可以在其中将详细信息输入时间表并将其存储在手机上 我尝试使用 localS
  • 如何计算Android应用程序中两点之间的距离

    在我的应用程序中 我试图计算一个人从一个地方到另一个地方的旅行距离 为此 我使用半正矢公式 R earth s radius mean radius 6 371km lat lat2 lat1 long long2 long1 a sin
  • 为什么线程不停止?

    我的服务生成一个新线程 并根据通常推荐java中断 的方法 当我停止服务时 我会在 onDestroy 中停止线程 服务停止 到达中断代码 然而 很快线程就会从 Runnable 的开头重新启动 public class DoScan ex
  • 使用欧氏距离在 numpy 数组列表中查找 numpy 数组的最近邻居

    我有一个 n 维向量 我想使用欧几里得距离在 n 维向量列表中找到它的 k 个最近邻 我编写了以下代码 k 10 它可以工作 但运行速度太慢 我想知道是否有更优化的解决方案 def nearest neighbors value array
  • MVVM 将 RelayCommand CanExecute 绑定到属性?

    我有一个计时器和三个按钮来控制它 开始 停止和暂停 每个按钮都绑定到一个 RelayCommand 我有一个 TimerState 类型的属性enum TimerState 这对于设置各种 GUI 元素很有用 有没有办法以某种方式将 Rel
  • 根据空格或“双引号字符串”将字符串解析为数组

    我试图获取用户输入字符串并解析为一个名为 char entire line 100 的数组 其中每个单词都放在数组的不同索引处 但如果字符串的一部分用引号封装 则应将其放在单个索引中 所以如果我有 char buffer 1024 0 fg
  • 无法获取托管类型的地址、获取其大小或声明指向托管类型(“类型名称”)的指针

    如果我的结构中有一个或多个 System String 此错误将停止编译还有其他方式存储字符串吗 我尝试过这样的事情 private long B ID private byte C Name private byte C Address
  • 互斥体未释放

    我的 c WinForm 解决方案包含多个项目 其中包括包含 frmAdmin 的管理项目和包含 frmUser 的用户项目 第三个项目包含 frmTimer 它有一个定期启动 frmUser 的计时器 我希望 frmTimer 在 frm