WinForms application hang due to SystemEvents.OnUserPreferenceChanged event

后端 未结 4 1003
情话喂你
情话喂你 2020-11-29 10:48

I\'ve been dealing with a strange application hang in my clients installations. After trying several things i reached the conclusion that without a dump it won\'t work. So I

4条回答
  •  自闭症患者
    2020-11-29 11:36

    The freezing issue due to SystemEvents.OnUserPreferenceChanged is quite common bug and here is a Microsoft explanation and recommendation how to fix it.

    Here is the function you can invoke any time (before or even after freeze) to find out which particular controls subscribed to SystemEvents was created on wrong threads and thus could freeze your app:

        private static void CheckSystemEventsHandlersForFreeze()
        {
            var handlers = typeof(SystemEvents).GetField("_handlers", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
            var handlersValues = handlers.GetType().GetProperty("Values").GetValue(handlers);
            foreach (var invokeInfos in (handlersValues as IEnumerable).OfType().ToArray())
            foreach (var invokeInfo in (invokeInfos as IEnumerable).OfType().ToArray())
            {
                var syncContext = invokeInfo.GetType().GetField("_syncContext", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(invokeInfo);
                if (syncContext == null) throw new Exception("syncContext missing");
                if (!(syncContext is WindowsFormsSynchronizationContext)) continue;
                var threadRef = (WeakReference) syncContext.GetType().GetField("destinationThreadRef", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(syncContext);
                if (!threadRef.IsAlive) continue;
                var thread = (Thread)threadRef.Target;
                if (thread.ManagedThreadId == 1) continue;  // Change here if you have more valid UI threads to ignore
                var dlg = (Delegate) invokeInfo.GetType().GetField("_delegate", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(invokeInfo);
                MessageBox.Show($"SystemEvents handler '{dlg.Method.DeclaringType}.{dlg.Method.Name}' could freeze app due to wrong thread: "
                                + $"{thread.ManagedThreadId},{thread.IsThreadPoolThread},{thread.IsAlive},{thread.Name}");
            }
        }
    
        

    提交回复
    热议问题