WinForms application hang due to SystemEvents.OnUserPreferenceChanged event

后端 未结 4 1010
情话喂你
情话喂你 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:32

    Following Vlad code, I have found a way to unsubscribe the system events on all objects subscribed out of the main UI thread.

    This code works for me and it is solving years of pain dealing with systemevents:

    public static void UnsubscribeSystemEvents()
    {
        try
        {
            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 = (System.Threading.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);
                    var handler = (UserPreferenceChangedEventHandler)Delegate.CreateDelegate(typeof(UserPreferenceChangedEventHandler), dlg.Target, dlg.Method.Name);
                    SystemEvents.UserPreferenceChanged -= handler;
                }
        }
        catch ()
        {                
            //trace here your errors
        }
    }
    
        

    提交回复
    热议问题