[.NET] Suspend Process 暂停批次执行

Mainframe主机环境中当批次执行太久,想释放CPU资源给其他批次执行时,我们会调整较低等级的Priority或者将这支JOB Cancel,最近搜寻了在开放系统.NET环境的作法。

笔记一下需求及解决方案:

由外部Process发出

  • 暂停批次
  • 被暂停的批次继续执行
  • 取消批次

1.Process vs Thread,先了解处理进程与执行序基本概念,刚好批次都是一个可执行文件,执行时就一个Process,然后视程序功能以单执行序或多执行序执行。

https://en.wikipedia.org/wiki/Thread_(computing)

2.Process内建的功能: 具备kill() 砍job 取消批次功能,但少了临时暂停 和 暂停工作继续执行

不过thread 执行序方法则有

如果要砍job,kill()很适合;但要暂停手边的工作,待会再继续执行,看起来要从thread这一层下手,但MSDN中的方法被标示为过时,原因是担心thread lock,但我们还是希望可以有这个功能,继续匍匐前进。

3.现成增加Process Extension解决方案: http://stackoverflow.com/questions/71257/suspend-process-in-c-sharp

果然在stackoverflow找到答案,利用调用Kernel32.lib中的SuspendThreadResumeThread功能来解决

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;


public static class ProcessExtension
{
    [DllImport("kernel32.dll")]
    static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
    [DllImport("kernel32.dll")]
    static extern uint SuspendThread(IntPtr hThread);
    [DllImport("kernel32.dll")]
    static extern int ResumeThread(IntPtr hThread);

    public static void Suspend(this Process process)
    {
        foreach (ProcessThread thread in process.Threads)
        {
            var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id);
            if (pOpenThread == IntPtr.Zero)
            {
                break;
            }
            SuspendThread(pOpenThread);
        }
    }
    public static void Resume(this Process process)
    {
        foreach (ProcessThread thread in process.Threads)
        {
            var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id);
            if (pOpenThread == IntPtr.Zero)
            {
                break;
            }
            ResumeThread(pOpenThread);
        }
    }
    public static void Print(this Process process)
    {
        Console.WriteLine("{0,8}    {1}", process.Id, process.ProcessName);
    }
}

[Flags]
public enum ThreadAccess : int
{
    TERMINATE = (0x0001),
    SUSPEND_RESUME = (0x0002),
    GET_CONTEXT = (0x0008),
    SET_CONTEXT = (0x0010),
    SET_INFORMATION = (0x0020),
    QUERY_INFORMATION = (0x0040),
    SET_THREAD_TOKEN = (0x0080),
    IMPERSONATE = (0x0100),
    DIRECT_IMPERSONATION = (0x0200)
}

Win kernel api规格书上提到

suspend方法

If the function succeeds, execution of the specified thread is suspended and the thread's suspend count is incremented.
Suspending a thread causes the thread to stop executing user-mode (application) code.

Resume方法

The ResumeThread function decrements a thread's suspend count. When the suspend count is decremented to zero,
the execution of the thread is resumed.

加上print方法

显示process id及process name

4.撰写一个输入"PID"和"处理选项"的方法来套

/// 
/// Process option 
/// 
public enum ProcessEnum
{
    Suspend = 0, Resume, Print, Kill
}
/// 
/// Control the process
/// 
/// The pid.
/// The option.
/// 
  
  
public string ctrlP(int PID, ProcessEnum OPTION)
{
    try
    {
        var p = Process.GetProcessById(PID);
        if (p != null)
        {
            switch (OPTION)
            {     
                case ProcessEnum.Suspend:
                    p.Suspend();
                    break;
                case ProcessEnum.Resume:
                    p.Resume();
                    break;
                case ProcessEnum.Print:
                    p.Print();
                    break;
                case ProcessEnum.Kill:
                    p.Kill();
                    break;
            }
            return string.Format("00:{0}({1})", PID, OPTION);
        }
        else
        {
            return string.Format("23:{0}({1})", PID, OPTION);
        }
    }
    catch (Exception e)
    {
        using (StreamWriter sw = File.AppendText(LogURL)) { sw.WriteLine("{0:u} Job Error:{1}({2}), {3}", DateTime.Now, PID, OPTION, e.ToString()); }
        return string.Format("99:{0}", e.ToString());
    }
}

5.执行中的批次程序 (状态:执行中),他是1支每5秒写1笔log的测试程序,总共要写10次log

6.调用Suspend()后,状态-(已暂止),从数据库观察,程序已经写了3次log

调用Resume()后,批次也继续将剩余的7次log工作完成了,目前测试单执行序process 暂止都很正常。

之后有时间继续来测试多执行序的process 或 改用powershell cmdlet操作 process。

原文:大专栏  [.NET] Suspend Process 暂停批次执行


猜你喜欢

转载自www.cnblogs.com/petewell/p/11495768.html