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 オブジェクトを再度参照しません。 オブジェクトは、 メソッドと WaitForPendingFinalizers メソッドの呼び出しCollectにもかかわらず、 メソッドの Main 30 秒間保持されます。

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 操作を実行せず、パラメーターとして渡されるオブジェクトの有効期間を延長する以外に副作用を生成しません。

適用対象