ホームページ > バックエンド開発 > C++ > 親プロセスがC#で終了したときに、子どものプロセスが終了するようにするにはどうすればよいですか?

親プロセスがC#で終了したときに、子どものプロセスが終了するようにするにはどうすればよいですか?

DDD
リリース: 2025-01-25 04:40:11
オリジナル
305 人が閲覧しました

How Can I Ensure Child Processes Terminate When the Parent Process Ends in C#?

C# における親プロセスの終了が子プロセスの終了に及ぼす影響

ソフトウェア開発では、親プロセスが終了したときの子プロセスの動作を処理することが、システムの安定性を維持するために重要です。親プロセスによって複数の子プロセスが生成される場合、それらの子プロセスが親プロセスとともに終了するようにすることが重要です。この記事では、一般的な問題について説明します。System.Diagnostics.Process クラスを使用して生成された子プロセスは、メイン アプリケーションがクラッシュしたり、タスク マネージャーによって強制終了された場合でも存続します。

ジョブ オブジェクト: 親子プロセス階層のソリューション

子プロセスと親プロセス間の依存関係を確立するには、「ジョブ オブジェクト」と呼ばれる機能を使用できます。ジョブ オブジェクトを使用すると、プロセス間に階層関係を作成できます。親ジョブ オブジェクトが終了すると、関連するすべての子プロセスも終了します。

次のコードは、ジョブ オブジェクトを使用して子プロセスの依存関係を管理する方法を示しています。

<code class="language-csharp">using System;
using System.Runtime.InteropServices;
using System.Diagnostics;

public class Job : IDisposable
{
    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    static extern IntPtr CreateJobObject(IntPtr a, string lpName);

    [DllImport("kernel32.dll")]
    static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);

    private IntPtr _handle;
    private bool _disposed = false;

    public Job()
    {
        _handle = CreateJobObject(IntPtr.Zero, null);

        JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
        info.LimitFlags = 0x2000; // JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE

        JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
        extendedInfo.BasicLimitInformation = info;

        int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
        IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
        Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

        if (!SetInformationJobObject(_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
            throw new Exception($"无法设置信息。错误:{Marshal.GetLastWin32Error()}");

        Marshal.FreeHGlobal(extendedInfoPtr);
    }


    public void AddProcess(Process process)
    {
        if (!AssignProcessToJobObject(_handle, process.Handle))
            throw new Exception($"无法将进程分配到作业对象。错误:{Marshal.GetLastWin32Error()}");
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
            return;

        if (disposing) { }

        Close();
        _disposed = true;
    }

    public void Close()
    {
        if (_handle != IntPtr.Zero)
        {
            Win32.CloseHandle(_handle);
            _handle = IntPtr.Zero;
        }
    }
}

internal static class Win32
{
    [DllImport("kernel32.dll")]
    internal static extern bool CloseHandle(IntPtr hObject);
}

//  必要的结构体定义  (根据需要补充完整)
enum JobObjectInfoType
{
    ExtendedLimitInformation = 9
}

[StructLayout(LayoutKind.Sequential)]
internal struct IO_COUNTERS
{
    public UInt64 ReadOperationCount;
    public UInt64 WriteOperationCount;
    public UInt64 OtherOperationCount;
    public UInt64 ReadTransferCount;
    public UInt64 WriteTransferCount;
    public UInt64 OtherTransferCount;
}

[StructLayout(LayoutKind.Sequential)]
internal struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
    public Int64 PerProcessUserTimeLimit;
    public Int64 PerJobUserTimeLimit;
    public UInt32 LimitFlags;
    public UIntPtr MinimumWorkingSetSize;
    public UIntPtr MaximumWorkingSetSize;
    public UInt32 ActiveProcessLimit;
    public UInt32 Affinity;
    public UInt32 PriorityClass;
    public UInt32 SchedulingClass;
}

[StructLayout(LayoutKind.Sequential)]
internal struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
    public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
    public IO_COUNTERS IoInfo;
    public UInt64 ProcessMemoryLimit;
    public UInt64 JobMemoryLimit;
    public UInt64 PeakProcessMemoryUsed;
    public UInt64 PeakJobMemoryUsed;
}</code>
ログイン後にコピー

子プロセスを作成した後、AddProcess() メソッドを呼び出して、確立されたジョブ オブジェクトに関連付けます。 必要な構造定義と IDisposable インターフェースの実装がコードに追加されているだけでなく、リソースが正しくリリースされていることに注意してください。

以上が親プロセスがC#で終了したときに、子どものプロセスが終了するようにするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート