다음 코드는 mdi 형식으로 창을 만드는 코드입니다. 아이디어는 존재하는 경우 특정 유형의 창을 작성하거나 이미 인스턴스가있는 경우 앞에 가져 오는 것입니다.Wpf 창 만들기 잠금
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
에서 무시된다는 것을 발견했습니다. 따라서 두 번째 호출이 사전에 도착하면 이전 인스턴스를 찾지 않고 창을 다시 만듭니다.
왜 이런 일이 발생하는지 알고 계십니까? 그리고이 상황을 처리하는 올바른 방법은 무엇입니까?
조금 더 많은 정보를 제공하려면 wtf가 동일한 코드에서 두 번 수행하는 스레드가 동일한 스레드 (잠금이 작동하지 않는 이유 설명)가 아닌 것 같습니다. –
STA 스레드에서 * lock *을 사용하는 것은 불법입니다. CLR은 메시지 루프를 펌핑하여이를 보완합니다. 클릭과 같이 Windows 메시지에 의해 트리거 된 이벤트의 재진입 실행이 발생합니다. UI 스레드에서 UI 관련 코드 만 실행하십시오 (필요한 경우 Dispatcher.BeginInvoke()). 그러므로 * lock *을 사용할 필요가 없습니다. –
그 정보를 주셔서 감사합니다, 내가 해왔 던 대부분의 윈도우 프로그래밍은 ASP.NET에 있었기 때문에 나는 그것을 몰랐습니다. 이 경우에는 실제로 스레드에서 실행되는 UI 관련 코드입니다. Form을 작성하고 리턴하지만 다른 방법으로는 그렇지 않습니다. –