안녕하세요
막히는 것이 있어 이렇게 오랜만에 질문 올립니다.
wpf 로 multi dispatcher 를 이용한 UI 처리 작업을 진행 중에 있는데요.
첨부한 예제의 UIEntrance 클래스를 이용해 스레드를 분리하여 처리하는 방식으로 작성을 하였습니다.
그런데 간헐적으로 Post 한 메시지들을 반응이 없는 경우가 발생합니다.
크게 두 가지 경우가 발생하는데요.
첫번째는 Post 시 넘긴 SendOrPostCallback 이 무시되는 것 처럼 보이는 경우입니다.
일단 스택을 따라가 보면 WindowsBase.dll!System.Windows.Threading.Dispatcher.GetMessage
여기서 멈춰 있는데요. 이거는 그냥 메시지 펌핑을 하는 스레드를 표시하는 거라 의미있는 정보가 아닌 것 같습니다.
디버그 트레이스를 찍어서 표시를 해봐도 정상적으로 Post까지 잘 넘어 갔는데
간헐적으로 딱 저 상태에서 반응이 없는 상황이 발생합니다.
(Go 버튼을 제대로 눌렀는데 새 창이 안 뜨는 경우 확인하면 새로운 스레드가 생성되었지만 스택이 저 위치에서 멈춰 있습니다.)
그러다가 다시 Go 버튼을 누르면 새로운 스레드로 새 창이 열립니다.
창이 열리지 않고 스레드만 생성된 경우 살아있는 스레드 때문에 정상 종료가 안 되는 문제도 있습니다.
스레드 죽이는 거야 어떻게든 하면 되겠지만
GetMessage 에서 멈춰서 작업을 밀어 넣어도 반응이 없는 경우는 어떻게 해야할지 난감합니다.
또 다른 경우는
실제 업무에서 사용하는 부분에서 발생하는 문제인데
첫 번째와 같은 방식이지만 Window 를 show 하기 전까지 새로 생성된 dispatcher로 좀 더 많은 작업을 하는 것 정도의 차이입니다.
증상은 위와 같이 반응이 없는 것은 같으나 좀 더 진행된 상태의 스택이 표시되는 경우 입니다.
(이 부분은 첨부한 예제로 재현이 안 되네요...)
현상은 동일한데 아래와 같은 스택이 표시됩니다.
WindowsBase.dll!System.Windows.Threading.DispatcherSynchronizationContext.Wait
WindowsBase.dll!System.Windows.Threading.DispatcherSynchronizationContext.Wait(System.IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
mscorlib.dll!System.Threading.SynchronizationContext.InvokeWaitMethodHelper(System.Threading.SynchronizationContext syncContext, System.IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
[Native to Managed Transition]
mscorlib.dll!System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle waitableSafeHandle, long millisecondsTimeout, bool hasThreadAffinity, bool exitContext)
mscorlib.dll!System.Threading.WaitHandle.WaitOne(int millisecondsTimeout, bool exitContext)
mscorlib.dll!System.Threading.WaitHandle.WaitOne()
PresentationCore.dll!System.Windows.Input.PenThreadWorker.WorkerGetTabletsInfo()
PresentationCore.dll!System.Windows.Input.StylusLogic.GetDeviceCount()
PresentationCore.dll!System.Windows.Input.StylusLogic.TabletDevices.get()
PresentationCore.dll!System.Windows.Input.StylusLogic.RegisterHwndForInput(System.Windows.Input.InputManager inputManager, System.Windows.PresentationSource inputSource)
PresentationCore.dll!System.Windows.Interop.HwndStylusInputProvider.HwndStylusInputProvider(System.Windows.Interop.HwndSource source)
PresentationCore.dll!System.Windows.Interop.HwndSource.Initialize(System.Windows.Interop.HwndSourceParameters parameters)
PresentationCore.dll!System.Windows.Interop.HwndSource.HwndSource(System.Windows.Interop.HwndSourceParameters parameters)
PresentationFramework.dll!System.Windows.Window.CreateSourceWindow(bool duringShow)
PresentationFramework.dll!System.Windows.Window.CreateSourceWindowDuringShow()
PresentationFramework.dll!System.Windows.Window.SafeCreateWindowDuringShow()
PresentationFramework.dll!System.Windows.Window.ShowHelper(object booleanBox)
PresentationFramework.dll!System.Windows.Window.Show()
Mango.Service.dll!Mango.Service.Services.TableManagerService.CreateTable<Mango.Table.Holdem.Views.HoldemTableWindow,Mango.Table.Holdem.ViewModels.HoldemTableContainerViewModel,Mango.Table.Holdem.Interfaces.IHoldemCallbackViewModel>.AnonymousMethod__1(System.Guid value) Line 53
mscorlib.dll!System.Collections.Concurrent.ConcurrentDictionary<System.Guid,Mango.Define.Models.TableManagerInfoModel<System.Windows.Window>>.GetOrAdd(System.Guid key, System.Func<System.Guid,Mango.Define.Models.TableManagerInfoModel<System.Windows.Window>> valueFactory)
Mango.Service.dll!Mango.Service.Services.TableManagerService.CreateTable<Mango.Table.Holdem.Views.HoldemTableWindow,Mango.Table.Holdem.ViewModels.HoldemTableContainerViewModel,Mango.Table.Holdem.Interfaces.IHoldemCallbackViewModel>(Mango.Define.Models.TableCreationModelBase creationModel) Line 25
Mango.Table.Holdem.dll!Mango.Table.Holdem.Utilities.HoldemTableCreator.CreateTable(Mango.Table.Holdem.Models.HoldemTableCreationModel creationModel) Line 24
!Mango.ViewModels.MonitoringLobbyWindowViewModel.ConnectAndCreateTable(Mango.Table.Holdem.Models.HoldemTableCreationModel creationModel) Line 361
!Mango.ViewModels.MonitoringLobbyWindowViewModel.TableOpen(object da) Line 329
[Resuming Async Method]
System.Threading.Tasks.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<Mango.ViewModels.MonitoringLobbyWindowViewModel..<TableOpen>b__d>(ref Mango.ViewModels.MonitoringLobbyWindowViewModel..<TableOpen>b__d stateMachine)
System.Threading.Tasks.dll!System.Runtime.CompilerServices.AsyncVoidMethodBuilder.Start<Mango.ViewModels.MonitoringLobbyWindowViewModel..<TableOpen>b__d>(ref Mango.ViewModels.MonitoringLobbyWindowViewModel..<TableOpen>b__d stateMachine)
!Mango.ViewModels.MonitoringLobbyWindowViewModel.TableOpen.AnonymousMethod__d(object da)
Mango.Presentation.dll!Mango.Presentation.Entrance.UISynchronizationEntrance.Post.AnonymousMethod__2() Line 189
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs)
WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler)
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl()
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(object state)
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state)
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke()
WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue()
WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs)
WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler)
WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs)
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam)
[Native to Managed Transition]
[Managed to Native Transition]
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame)
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame)
WindowsBase.dll!System.Windows.Threading.Dispatcher.Run()
Mango.Presentation.dll!Mango.Presentation.Entrance.UISynchronizationEntrance..ctor.AnonymousMethod__0() Line 95
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state)
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state)
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart()
중간 즈음에
Mango.Service.dll!Mango.Service.Services.TableManagerService.CreateTable<Mango.Table.Holdem.Views.HoldemTableWindow,Mango.Table.Holdem.ViewModels.HoldemTableContainerViewModel,Mango.Table.Holdem.Interfaces.IHoldemCallbackViewModel>.AnonymousMethod__1(System.Guid value) Line 53
요부분에서 새 Window 를 Show() 하는데 StylusLogic 을 찾더니 Waiting에 빠져버립니다.
개발 환경은 Windows7에 stylus 장치 없이 순수한 Window 환경이고 .net 4.0 을 사용하고 있는데요.
유사한 증상이 있는 사람이 있긴 하더군요.
https://social.msdn.microsoft.com/Forums/vstudio/en-US/71543c67-bc3b-4df8-acb8-324a1b32e37b/random-hangup-when-showing-a-dialog-on-a-touchscreen-on-win8?forum=wpf
Window 를 Show 한 이후 스택이 유사해서 댓글에 달린 핫픽스를 찾아 설치해 보려 했는데 설치가 안 되더군요.
(설치한다고 증상이 없어진다는 보장도 없긴 하지만...)
근데 저는 터치 스크린 따위 없고 Win7 이라 환경이 유사하지는 않는데
Multi Dispatcher 를 이용해 여러 창을 띄워 제어하겠다는 의도로 만든 것이 이런 문제를 발생하는 건지... 참 난감합니다.
사실 이 증상 때문에 테스트 예제를 만든 건데 막상 위 두 번째 문제는 테스트 예제로 재현이 안 되네요. =ㅅ=;;;
아마도 두 번째 문제 부분은 정보가 부족해서 분석이 불가능하시리라 생각하지만
혹시 알고 계신 증상이라거나 아니면 이 정도로도 해결 방법을 알고 계실까 해서 올렸습니다.
제 생각에는 첫 번째와 두 번째가 완전히 다른 원인 같지는 않은 것 같은데
어찌됐든 한 가지라도 해결할 수 있었으면 좋겠다고 생각하고 있습니다.
염치 불구하고 혹시 한 번 봐 주실 수 있을 지 부탁드립니다.
바쁘실 텐데 죄송합니다.
[최초 등록일: ]
[최종 수정일: 7/9/2015]