在 C# 中与有时冻结的进程进行通信

问题描述 投票:0回答:1

我正在尝试构建一个

C#
应用程序,使用
MPC-HC's
API
来控制视频播放器。它来回发送 Windows 消息并且正在工作。

除了

MPC-HC
有时会冻结,当它发生时,我的应用程序也会冻结。

有什么办法可以
1.防止我的应用程序冻结
2. 检测

MPC-HC
窗口是否响应
3. 终止进程并重新打开媒体播放器窗口(如果冻结)

我已经能够为 2 和 3 编写代码,以及在发送命令之前检测响应能力,但是如果

MPC-HC
在发送 API 命令时冻结,我的应用程序就会冻结,我无能为力。

有什么解决办法吗?也许中间有第三个进程,而我的应用程序只会以无法冻结主应用程序的方式与该中间进程通信(如果可能的话)?

编辑:原来我之前使用“await”关键字测试了多线程,它实际上并没有启动任何新线程,这就是进程仍然冻结的原因!如果我正确地创建了一个新线程,那就没问题了......这段代码可以工作并替换我在下面编写的整个程序

Dim T As New Task(Function() Comm.SendMsg(CommWnd.SYSMSG.WM_COPYDATA, cmd, param))
T.Start()
If T.Wait(3000) = False Then
    MpcProcess.Kill()
End If

这就是当你在学习新功能方面落后时会发生的事情

c# process freeze
1个回答
0
投票

我首先尝试创建单独的线程,但这不起作用。整个应用程序仍然冻结。

但是,我确实找到了解决方案:创建一个监视视频播放器的新进程。如果它冻结,它会冻结我的主应用程序,但单独的进程仍在运行并且可以杀死它。

这是此代码,以防其他人遇到类似的问题。

文件:Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProcessWatcher {
    public class Program {
        private static WatcherThread watcher;

        /// <summary>
        /// Application entry point
        /// </summary>
        /// <param name="args">Command-line parameters</param>
        static void Main(string[] args) {
            // args = new string[] { "mpc-hc", "" };

            if (args.Length < 2) {
                System.Windows.Forms.MessageBox.Show(
@"Call with these parameters
ProcessWatcher [WatchProcess] [HostProcess] [Interval]
[WatchProcess]: Name of the process to monitor and kill if frozen.
[HostProcess]: When specified host process stops, end program.
[Interval]: (optional) Interval in milliseconds between checks. Default is 2000.

Example:
ProcessWatcher mpc-hc NaturalGroundingPlayer 2000");
                return;
            }

            string WatchProcess = args[0];
            string HostProcess = args[1];
            int Interval = args.Length > 2 ? Int32.Parse(args[2]) : 2000;

            watcher = new WatcherThread(WatchProcess, HostProcess, Interval);
            System.Windows.Forms.Application.Run();
        }
    }
}

文件:ProcessWatcher.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;

namespace ProcessWatcher {
    /// <summary>
    /// Checks regularly whether specified process is responsive. If not, kill it.
    /// </summary>
    public class WatcherThread {
        private string processWatch;
        private string processHost;
        private Timer timer;

        public WatcherThread(string processWatch, string processHost, int interval) {
            this.processWatch = processWatch;
            this.processHost = processHost;
            timer = new Timer(KillIfFrozen, null, interval, interval);
        }

        /// <summary>
        /// Kills the watched process if it is not responsive.
        /// </summary>
        /// <param name="state">null</param>
        public void KillIfFrozen(Object state) {
            Process[] ProcessList = Process.GetProcessesByName(processWatch);
            foreach (Process item in ProcessList) {
                if (item.Responding == false) {
                    // Wait 1500ms for the process to respond
                    for (int i = 0; i < 6; i++) {
                        Thread.Sleep(250);
                        if (item.Responding)
                            break;
                    }

                    // If still not responsive, kill process.
                    if (item.Responding == false) {
                        try {
                            // This throws an "Access denied" exception but still stops the process.
                            item.Kill();
                        } catch {}
                    }
                }
            }

            // If host process is closed, end program.
            if (!string.IsNullOrEmpty(processHost)) {
                ProcessList = Process.GetProcessesByName(processHost);
                if (ProcessList.Length == 0) {
                    System.Windows.Forms.Application.Exit();
                }
            }
        }
    }
}

然后,在主应用程序中使用 Process.Start 来运行该应用程序。当主应用程序停止时,它会检测到它并停止。

现在,为了在 Visual Studio 中结束执行时停止主应用程序进程,在主应用程序项目属性下,您必须进入“调试”并禁用“启用 Visual Studio 托管进程”

© www.soinside.com 2019 - 2024. All rights reserved.