2016-04-07 18 views
1

Ich habe festgestellt, dass das Abonnieren und Abmelden von Console.CancelKeyPress das nächste Abonnement zum Scheitern bringt.abmelden und dann Console.CancelKeyPress abonnieren

Noch seltsamer: Start von mit einem leeren Eventhandler behebt dies.

Kann jemand dieses Verhalten erklären?

class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.TreatControlCAsInput = false; 
// 2:  uncomment following for an unexpected fix... 
      //Console.CancelKeyPress += (s, a) => { }; 

      Console.CancelKeyPress += Handler_1; 
      Console.WriteLine("Press Ctr+C to prove that Handler_1 cancels key press."); 
      Console.ReadLine(); 

      Application.DoEvents(); // make sure events are handled before unsubscribe 
      Console.CancelKeyPress -= Handler_1; 

// 1:  uncomment following to prove failure... 
      //Console.CancelKeyPress += Handler_2; 
      //Console.WriteLine("Press Ctr+C to prove that Handler_2 cancels key press."); 
      //Console.ReadLine(); 

      Application.DoEvents(); // make sure events are handled 
      Console.WriteLine("End of demo, type something to prove application is still responsive."); 
      Console.ReadLine(); 
     } 

     private static void Handler_1(object sender, ConsoleCancelEventArgs args) 
     { 
      args.Cancel = true; 
      Console.WriteLine("Key press is canceled by Handler_1"); 
     } 

     private static void Handler_2(object sender, ConsoleCancelEventArgs args) 
     { 
      args.Cancel = true; 
      Console.WriteLine("Key press is canceled by Handler_2"); 
     } 
    } 
+0

Welche Art von Fehler haben Sie? –

+0

Nun, der zweite Eventhandler reagiert nicht auf ctr + c. –

Antwort

2

Es ist ein Fehler in der Implementierung CancelKeyPress

public static event ConsoleCancelEventHandler CancelKeyPress { 
       [System.Security.SecuritySafeCritical] // auto-generated 
       [ResourceExposure(ResourceScope.Process)] 
       [ResourceConsumption(ResourceScope.Process)] 
       add { 
        new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 

        lock(InternalSyncObject) { 
         // Add this delegate to the pile. 
         _cancelCallbacks += value; 

         // If we haven't registered our control-C handler, do it. 
         if (_hooker == null) { 
          _hooker = new ControlCHooker(); 

// BUG: after you unsubscribe from CancelKeyPress it becomes null 
// and when you subscribe to CancelKeyPress again the call below will never be called. In the Remove part they will not set _hooker to null. 
         _hooker.Hook(); 
        } 
       } 
      } 
      [System.Security.SecuritySafeCritical] // auto-generated 
      [ResourceExposure(ResourceScope.Process)] 
      [ResourceConsumption(ResourceScope.Process)] 
      remove { 
       new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 

       lock(InternalSyncObject) { 
        // If count was 0, call SetConsoleCtrlEvent to remove cb. 
        _cancelCallbacks -= value; 
        Contract.Assert(_cancelCallbacks == null || _cancelCallbacks.GetInvocationList().Length > 0, "Teach Console::CancelKeyPress to handle a non-null but empty list of callbacks"); 
        if (_hooker != null && _cancelCallbacks == null) 
         _hooker.Unhook(); 
//BUG: It Unhooks but does not set _hooker to null. 
        } 
       } 
      } 
+1

Also: Fehler in der CancelKeyPress-Implementierung, umgehen Sie, indem Sie mit einem leeren Handler beginnen und ihn niemals entfernen. –