首頁 >後端開發 >C++ >當父程進程以C#結束時,如何確保子進程終止?

當父程進程以C#結束時,如何確保子進程終止?

DDD
DDD原創
2025-01-25 04:40:11327瀏覽

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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn