6
12

More than 5 years have passed since last update.

C# System.Diagnositic.Processを非同期実行。(async/awaitで使用する)

Posted at

はじめに

非同期のコードはいくつかパターンがありますが、なるべく一つにしたいため、async/awaitに統一できないか検討するなかで、Process.StartとExitedイベントのパターンをasync/awaitで記述する方法を見つけたのでメモしておきます。

参考

下記、stackoverflowを参考にしました。ほぼリンク先の通りです。

https://stackoverflow.com/questions/10788982/is-there-any-async-equivalent-of-process-start

コード

ある2つのファイル(sourceFileName, destinationFileName)に対してFCコマンドを実行し、結果を取得するサンプルです。

AsyncProcess.cs
private async Task StartCommandAsync(string sourceFileName, string destinationFileName) {
    //Processを非同期に実行
    using (Process process = this.CreateFCProcess(sourceFileName, destinationFileName)) {
        await this.StartCommandAsync(process);
    }
}

private Task StartCommandAsync(Process process) {
    var tcs = new TaskCompletionSource<bool>();
    bool started = false;
    process.Exited += (sender, args) => {
        tcs.SetResult(true);
    };
    process.OutputDataReceived += (sender, args) => {
        if (!string.IsNullOrEmpty(args.Data)) {
            this.m_FCResult += $"{args.Data}\n";
            }
        };
    process.ErrorDataReceived += (sender, args) => {
        if (!string.IsNullOrEmpty(args.Data)) {
            this.m_FCResult += $"Error : {args.Data}\n";
        }
    };

    //プロセスからの情報を受け取る変数の初期化
    this.m_FCResult = "";

    //プロセスの開始
    started = process.Start();
    process.BeginOutputReadLine();
    process.BeginErrorReadLine();

    return tcs.Task;
}

private Process CreateFCProcess(string sourceFileName,string destinationFileName) {
    ProcessStartInfo info = new ProcessStartInfo() {
        FileName = "FC",
        Arguments = $"\"{sourceFileName}\" \"{destinationFileName}\"",
        CreateNoWindow = true,
        UseShellExecute = false,
        RedirectStandardOutput = true,
        RedirectStandardError = true
    };

    Process process = new Process() {
        StartInfo = info,
        EnableRaisingEvents = true,
    };
    return process;
}

おわりに

最終的には、Exitedイベント内で、FCの結果をProcess.ExitCodeで取得したりしていますが、サンプルには含めませんでした。
AsParallelと組み合わせて並列化してみようかとチャレンジしてみましたが、どうも正しくExitCodeが取れず、断念。
結局、この例はあまり非同期実行する意味が無いサンプルになっている状態です。

※実際は、もっと時間のかかる自作VBScriptを非同期で実行するために調べていたのですが、サンプルとしてわかりにくくなるかなと思い、Window標準コマンドを実行するサンプルにしました。

6
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
12