互斥体未释放

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(使用前将#替换为@)

互斥体未释放 的相关文章

随机推荐

  • 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