1

ビデオプレーヤーの制御にC#使用するアプリケーションを構築しようとしています。MPC-HC's APIWindowsメッセージを前後に送信し、機能しています。

それが時々フリーズすることを除いて、MPC-HCそれがフリーズすると、私のアプリケーションもフリーズします。

できる方法はありますか
1. アプリケーションがフリーズするのを防ぐ2.ウィンドウが応答して
いるかどうかを検出する 3. プロセスを強制終了し、フリーズした場合はメディア プレーヤー ウィンドウを再度開く MPC-HC

2と3のコードを書いたり、コマンド送信前に応答性を検知するMPC-HCことはできたのですが、APIコマンド送信時にフリーズするとアプリがフリーズしてどうしようもありません。

回避策はありますか?おそらく、中間に3番目のプロセスがあり、私のアプリケーションは、メインアプリをフリーズできない方法でその中間プロセスとのみ通信します(可能であれば)?

編集:以前に「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

新機能の勉強が遅れるとこうなる

4

1 に答える 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 ホスティング プロセスを有効にする] を無効にする必要があります。

于 2014-08-21T17:00:39.863 に答える