Wpf创建窗口锁定

本文关键字:锁定 窗口 创建 Wpf | 更新日期: 2023-09-27 18:25:29

I下面的代码以mdi形式创建窗口。其想法是,如果某个类型的窗口不存在,则创建它;如果已经有实例,则将其放在前面。

  public static object CreateWindow(Type windowType, params object[] args)
    {
        try
        {
            lock (_definitionToWindow)
            {
                var def = new WindowDefinition {ControlType = windowType, Args = args};
                System.Windows.Forms.Form win = null;
                if (_definitionToWindow.TryGetValue(def, out win))
                {                      
                    win.Activate();
                    return win;
                }      
                System.Windows.Controls.Control uiElement =
                    (System.Windows.Controls.Control) Activator.CreateInstance(windowType, args);

                object result = null;
                if (uiElement is Window)
                    result = WpfMdiHelper.ShowWpfWindowInMdi((Window) uiElement);
                else
                    result = WpfMdiHelper.ShowWpfControlInMdi((System.Windows.Controls.Control) uiElement);
                if (result is System.Windows.Forms.Form)
                {                       
                    _definitionToWindow.Add(def, result as System.Windows.Forms.Form);
                    lock (_windowslock)
                    {
                        _windows.Add((System.Windows.Forms.Form) result, uiElement as IHasViewModel);                           
                    }
                    ((System.Windows.Forms.Form) result).Disposed += new EventHandler(WindowsFactory_Disposed);
                }                
                return result;
            }
        }
        catch (Exception ex)
        {
            Logger.WriteError("Window creation exception", ex.ToString(), LogEntryCodes.UIException);
        }
        return null;
    }

代码或多或少是有效的,但当你点击一个按钮打开一个窗口时,它会快速连续打开几个类型的窗口。

在运行调试跟踪之后,我发现lock (_definitionToWindow)Activator.CreateInstance上的所有单击(看起来所有调用都是在同一个线程上进行的)和方法块绕过。因此,当第二个调用到达字典检查时,它没有找到任何以前的实例,并继续重新创建窗口。

有人知道为什么会发生这种事吗?以及处理这种情况的正确方法?

Wpf创建窗口锁定

这应该为您提供一个线程安全锁,该锁只允许一个调用程序进入CreateWindowImpl,即使它们在同一个线程上。与lock()不同,它不会阻塞任何线程。

static long Locked = 0;
static void CreateWindow(...)
{
   if(0 == Interlocked.Exchange(ref Locked, 1))
   {
      try
      {
         CreateWindowImpl(...);
      }
      finally 
      {
         Interlocked.Exchange(ref Locked, 0);
      }
   }
}