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
上的所有单击(看起来所有调用都是在同一个线程上进行的)和方法块绕过。因此,当第二个调用到达字典检查时,它没有找到任何以前的实例,并继续重新创建窗口。
有人知道为什么会发生这种事吗?以及处理这种情况的正确方法?
这应该为您提供一个线程安全锁,该锁只允许一个调用程序进入CreateWindowImpl,即使它们在同一个线程上。与lock()不同,它不会阻塞任何线程。
static long Locked = 0;
static void CreateWindow(...)
{
if(0 == Interlocked.Exchange(ref Locked, 1))
{
try
{
CreateWindowImpl(...);
}
finally
{
Interlocked.Exchange(ref Locked, 0);
}
}
}