GC.KeepAlive(Object) 方法

定义

引用指定对象,使其从当前例程开始到调用此方法的那一刻为止均不符合进行垃圾回收的条件。

public:
 static void KeepAlive(System::Object ^ obj);
public static void KeepAlive (object obj);
public static void KeepAlive (object? obj);
static member KeepAlive : obj -> unit
Public Shared Sub KeepAlive (obj As Object)

参数

obj
Object

要引用的对象。

示例

下面的代码示例在其 Main 方法的开头创建一个 对象,在调用 方法时,在结束之前不会再次引用该 KeepAlive 对象。 对象在方法的 30 秒持续时间内 Main 保留,尽管调用 Collect 了 和 WaitForPendingFinalizers 方法。

using namespace System;
using namespace System::Threading;
using namespace System::Runtime::InteropServices;

// A simple class that exposes two static Win32 functions.
// One is a delegate type and the other is an enumerated type.
public ref class MyWin32
{
public:

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

   delegate Boolean HandlerRoutine(    // A delegate type to be used as the Handler Routine for SetConsoleCtrlHandler.
   CtrlTypes CtrlType );

   // Declare the SetConsoleCtrlHandler function as external and receiving a delegate.

   [DllImport("Kernel32")]
   static Boolean SetConsoleCtrlHandler( HandlerRoutine^ Handler, Boolean Add );
};

public ref class MyApp
{
private:

   // 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 Test()
   {
      
      // Use interop to set a console control handler.
      MyWin32::HandlerRoutine^ hr = gcnew 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 );
   }

};

int main()
{
   MyApp::Test();
}
using System;
using System.Threading;
using System.Runtime.InteropServices;

// 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();
    }
}
open System
open System.Threading
open System.Runtime.InteropServices

// A simple module that exposes two static Win32 functions.
// One is a delegate type and the other is an enumerated type.
module MyWin32 =
    // An enumerated type for the control messages
    // sent to the handler routine.
    type CtrlTypes =
        | CTRL_C_EVENT = 0
        | CTRL_BREAK_EVENT = 1
        | CTRL_CLOSE_EVENT = 2
        | CTRL_LOGOFF_EVENT = 5
        | CTRL_SHUTDOWN_EVENT = 6

    // A delegate type to be used as the handler routine for SetConsoleCtrlHandler.
    type HandlerRoutine = delegate of CtrlTypes -> bool

    // Declare the SetConsoleCtrlHandler function
    // as external and receiving a delegate.
    [<DllImport "Kernel32">]
    extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add)

// A private static handler function in the MyApp class.
let handler (ctrlType: MyWin32.CtrlTypes) =
    let message =
        // Pattern match to handle the event type.
        match ctrlType with
        | MyWin32.CtrlTypes.CTRL_C_EVENT ->
            "A CTRL_C_EVENT was raised by the user."
        | MyWin32.CtrlTypes.CTRL_BREAK_EVENT ->
            "A CTRL_BREAK_EVENT was raised by the user."
        | MyWin32.CtrlTypes.CTRL_CLOSE_EVENT ->
            "A CTRL_CLOSE_EVENT was raised by the user."
        | MyWin32.CtrlTypes.CTRL_LOGOFF_EVENT ->
            "A CTRL_LOGOFF_EVENT was raised by the user."
        | MyWin32.CtrlTypes.CTRL_SHUTDOWN_EVENT ->
            "A CTRL_SHUTDOWN_EVENT was raised by the user."
        | _ -> "This message should never be seen!"

    // Use interop to display a message for the type of event.
    printfn $"{message}"
    true

// Use interop to set a console control handler.
let hr = MyWin32.HandlerRoutine handler
MyWin32.SetConsoleCtrlHandler(hr, true) |> ignore

// Give the user some time to raise a few events.
printfn "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.
printfn "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() |> ignore
Imports System.Threading
Imports System.Runtime.InteropServices

' 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 Shared Function SetConsoleCtrlHandler(ByVal Handler As HandlerRoutine, _
         ByVal Add As Boolean) As Boolean
   End Function


   ' A delegate type to be used as the handler routine 
   ' for SetConsoleCtrlHandler.
   Delegate Function HandlerRoutine(ByVal CtrlType As CtrlTypes) As [Boolean]

   ' 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
   End Enum
End Class

Public Class MyApp

   ' A private static handler function in the MyApp class.
   Shared Function Handler(ByVal CtrlType As MyWin32.CtrlTypes) As [Boolean]
      Dim message As [String] = "This message should never be seen!"

      ' A select case to handle the event type.
      Select Case CtrlType
         Case MyWin32.CtrlTypes.CTRL_C_EVENT
            message = "A CTRL_C_EVENT was raised by the user."
         Case MyWin32.CtrlTypes.CTRL_BREAK_EVENT
            message = "A CTRL_BREAK_EVENT was raised by the user."
         Case MyWin32.CtrlTypes.CTRL_CLOSE_EVENT
            message = "A CTRL_CLOSE_EVENT was raised by the user."
         Case MyWin32.CtrlTypes.CTRL_LOGOFF_EVENT
            message = "A CTRL_LOGOFF_EVENT was raised by the user."
         Case MyWin32.CtrlTypes.CTRL_SHUTDOWN_EVENT
            message = "A CTRL_SHUTDOWN_EVENT was raised by the user."
      End Select

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

      Return True
   End Function


   Public Shared Sub Main()
      ' Use interop to set a console control handler.
      Dim hr As New MyWin32.HandlerRoutine(AddressOf 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()
   End Sub
End Class

注解

方法的用途 KeepAlive 是确保存在对存在被垃圾回收器过早回收的风险的对象引用。 一种常见的情况是,在托管代码或数据中没有引用对象,但对象仍在非托管代码(如 Windows API、非托管 DLL 或使用 COM 的方法)中使用。

此方法引用 obj 参数,使该对象没有资格进行垃圾回收,从例程的开头到执行顺序(按执行顺序调用此方法)。 在指令范围的末尾(而不是开头)编写此方法,其中 obj 必须可用。

方法 KeepAlive 不执行任何操作,除了延长作为参数传入的 对象的生存期外,不会产生任何副作用。

适用于