Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
正在终止从嵌套线程启动的多个进程。。。C#_C#_Multithreading_Process_Nested_Kill - Fatal编程技术网

正在终止从嵌套线程启动的多个进程。。。C#

正在终止从嵌套线程启动的多个进程。。。C#,c#,multithreading,process,nested,kill,C#,Multithreading,Process,Nested,Kill,我是编程新手。我有一个启动线程的表单应用程序。从那时起,4个新线程被启动。每个线程都执行一系列命令行进程,如下所示: ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.WorkingDirectory ="C:\\BLA\\bin_windows"; startInfo.UseShellExecute = false; startInfo.RedirectStandardO

我是编程新手。我有一个启动线程的表单应用程序。从那时起,4个新线程被启动。每个线程都执行一系列命令行进程,如下所示:

ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.WorkingDirectory ="C:\\BLA\\bin_windows";
        startInfo.UseShellExecute = false;
        startInfo.RedirectStandardOutput = true;
        startInfo.CreateNoWindow = true;

            startInfo.FileName = "SomeProcess"
            Process p = Process.Start(startInfo);
        p.WaitForExit();
    foreach (Process p in System.Diagnostics.Process.GetProcessesByName("SomeProcess"))
    {
        try
        {
            p.Kill();
            p.WaitForExit(); // possibly with a timeout
        }
        catch
        { continue; }
    } 
当表单应用程序关闭时,它中止第一个线程(不是4个单独的线程)。 现在我的问题是,当我关闭表单时,如何强制进程“p”退出?? 我尝试了以下方法:

ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.WorkingDirectory ="C:\\BLA\\bin_windows";
        startInfo.UseShellExecute = false;
        startInfo.RedirectStandardOutput = true;
        startInfo.CreateNoWindow = true;

            startInfo.FileName = "SomeProcess"
            Process p = Process.Start(startInfo);
        p.WaitForExit();
    foreach (Process p in System.Diagnostics.Process.GetProcessesByName("SomeProcess"))
    {
        try
        {
            p.Kill();
            p.WaitForExit(); // possibly with a timeout
        }
        catch
        { continue; }
    } 
然而,这种方法对我来说似乎有点残酷,并不总是很好地工作。。。有没有一种方法可以让我只识别我自己启动的流程,然后终止它们? 非常感谢您的建议。
谢谢

您对已运行的进程几乎没有控制权。杀死他们是一种方法。如果进程是一个窗口应用程序(即有一个窗口),您可以尝试向其发送一条
WM_CLOSE
消息,这相当于单击窗口上的关闭按钮。同样,应用程序必须有一个可见或隐藏的窗口,因此它不能在每个应用程序上工作。大多数应用程序都有窗口,即使不可见

const uint WM_CLOSE = 0x10;

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, uint uMsg, int wParam, int lParam);

Process p = Process.GetProcessesByName("notepad").FirstOrDefault();
if(p != null)
{
    IntPtr hWnd = p.MainWindowHandle;
    SendMessage(hWnd, WM_CLOSE, 0, 0);
}
若要仅杀死/关闭您生成的进程,只需保留它们的
进程
对象,或者至少保留
p.MainWindowHandle
,如果您想使用我给您的方法。为此,请在类中使用类型为
ConcurrentBag
(或
ConcurrentBag
)的公共属性。它已经是线程安全的

编辑

正如有人指出的,您可以这样做来关闭流程的主窗口:

p.CloseMainWindow()

如果您的程序不应该一次运行两次,您可以在singleton上使用某种process manager:

internal sealed class ProcessManager
{
    private readonly IList<Process> processes;

    #region Singleton

    private static readonly object locker = new object();
    private static volatile ProcessManager instance;

    private ProcessManager()
    {
        processes = new List<Process>();
    }

    public static ProcessManager Instance
    {
        get
        {
            if (instance == null)
            {
                lock (locker)
                {
                    if (instance == null)
                    {
                        instance = new ProcessManager();
                    }
                }
            }

            return instance;
        }
    }

    #endregion

    public void AddProcess(Process process)
    {
        lock(processes)
        {
            processes.Add(process);
        }
    }

    public void TerminateAll()
    {
        lock(processes)
        {
            foreach (Process p in processes)
            {
                try
                {
                    p.Kill();
                    p.WaitForExit(); // possibly with a timeout
                }
                catch
                {
                     continue;
                }
            }
        }
    }
}

如果你不希望程序中有静态的东西(例如,你可以有它的一些实例),你可以使用这个类,但不需要singleton,只给每个线程一个实例。

如果你想关闭进程,不需要p/Invoke并发送WM\u close消息,只要在你的进程实例上调用这个方法就可以了(这将为您发送一个WM_CLOSE)。然后,您可以使用该方法后续发布您的本地视图

跟踪您已经开始的流程也相当容易

public static ConcurrentBag<Process> processes = new ConcurrentBag<Process>();
然后循环并关闭它们

foreach (var process in processes)
{
    if (!process.HasExited)
    {
        process.CloseMainWindow();
        process.Close();
    }
}

把你启动的所有进程列成一个全局列表怎么样?@dwrd--听起来不错--但我不知道怎么做…你能解释更多吗?谢谢!谢谢-因为它们是命令行程序,我认为它们没有windows?!或者?另外,最好只删除表单应用程序启动的程序。@timkado it sh你也可以在控制台应用程序上工作,因为它们确实有windows。要只杀死你产生的进程,保留它们的
进程
对象或至少
p.MainWindowHandle
,或者你可以用
公共静态ConcurrentBag进程=新的ConcurrentBag();
嘿,不知道ConcurrentBag类:)值得注意的是,你可以在内华达州的许多酒吧以非常合理的价格买到ConcurrentBags,不过在第五大JD之后,你最好排队。