2011-11-08 174 views
-1

我在GC.KeepAlive()上運行下面的代碼示例並將其註釋掉,但它是相同的。如何編碼,以便我可以看到差異。GC.KeepAlive()似乎沒有效果

// A simple class that exposes two static Win32 functions. 
// One is a delegate type and the other is an enumerated type. 
public class MyWin32 
{ 
    // Declare the SetConsoleCtrlHandler function 
    // as external and receiving a delegate. 
    [DllImport("Kernel32")] 
    public static extern Boolean SetConsoleCtrlHandler(HandlerRoutine Handler, 
     Boolean Add); 

    // A delegate type to be used as the handler routine 
    // for SetConsoleCtrlHandler. 
    public delegate Boolean HandlerRoutine(CtrlTypes CtrlType); 

    // An enumerated type for the control messages 
    // sent to the handler routine. 
    public enum CtrlTypes 
    { 
     CTRL_C_EVENT = 0, 
     CTRL_BREAK_EVENT, 
     CTRL_CLOSE_EVENT, 
     CTRL_LOGOFF_EVENT = 5, 
     CTRL_SHUTDOWN_EVENT 
    } 
} 

public class MyApp 
{ 
    // A private static handler function in the MyApp class. 
    static Boolean Handler(MyWin32.CtrlTypes CtrlType) 
    { 
     String message = "This message should never be seen!"; 

     // A switch to handle the event type. 
     switch(CtrlType) 
     { 
      case MyWin32.CtrlTypes.CTRL_C_EVENT: 
       message = "A CTRL_C_EVENT was raised by the user."; 
       break; 
      case MyWin32.CtrlTypes.CTRL_BREAK_EVENT: 
       message = "A CTRL_BREAK_EVENT was raised by the user."; 
       break; 
      case MyWin32.CtrlTypes.CTRL_CLOSE_EVENT: 
       message = "A CTRL_CLOSE_EVENT was raised by the user."; 
       break; 
      case MyWin32.CtrlTypes.CTRL_LOGOFF_EVENT: 
       message = "A CTRL_LOGOFF_EVENT was raised by the user."; 
       break; 
      case MyWin32.CtrlTypes.CTRL_SHUTDOWN_EVENT: 
       message = "A CTRL_SHUTDOWN_EVENT was raised by the user."; 
       break; 
     } 

     // Use interop to display a message for the type of event. 
     Console.WriteLine(message); 

     return true; 
    } 

    public static void Main() 
    {   

     // Use interop to set a console control handler. 
     MyWin32.HandlerRoutine hr = new MyWin32.HandlerRoutine(Handler); 
     MyWin32.SetConsoleCtrlHandler(hr, true); 

     // Give the user some time to raise a few events. 
     Console.WriteLine("Waiting 30 seconds for console ctrl events..."); 

     // The object hr is not referred to again. 
     // The garbage collector can detect that the object has no 
     // more managed references and might clean it up here while 
     // the unmanaged SetConsoleCtrlHandler method is still using it.  

     // Force a garbage collection to demonstrate how the hr 
     // object will be handled. 
     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 
     GC.Collect(); 

     Thread.Sleep(30000); 

     // Display a message to the console when the unmanaged method 
     // has finished its work. 
     Console.WriteLine("Finished!"); 

     // Call GC.KeepAlive(hr) at this point to maintain a reference to hr. 
     // This will prevent the garbage collector from collecting the 
     // object during the execution of the SetConsoleCtrlHandler method. 
     GC.KeepAlive(hr); 
     Console.Read(); 
    } 
} 

http://msdn.microsoft.com/en-us/library/system.gc.keepalive.aspx

感謝。

+2

您是否在調試模式下運行,和/或是否連接了調試器?在調試時,GC的攻擊性要小得多,因此要保持對象更長的時間。嘗試在發佈模式下編譯並在未連接調試器的情況下運行(Visual Studio中的Ctrl + F5)。 – LukeH

+0

謝謝你提醒我。 – Pingpong

回答

2
GC.KeepAlive(hr); 

本身就是(在後面的代碼)的參考...

所以hr不能在您的CAL GC.Collect()點(一個或多個)收集。

你預期會發生什麼?

相關問題