質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

1回答

1081閲覧

C# 複数のスレッドが全部終了するまで待機する方法が知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2022/07/24 08:32

提示コードの///コメント部内部のコードですがマルチスレッドですべてのスレッドが終了するまで待機してすべて終わったら次のコードに推移するという処理を書きたいのですが実装方法がわかりません。マルチタスクでいうTask.WhenAllのようなことがしたいです。現状では一つのスレッドですべての処理を行っています。このソフトは音楽ファイルをffmpegflac.m4aに変換する処理なのですがマルチスレッドで素早く終らせる方法が知りたいです。

cs

1using System; 2using System.Diagnostics; 3using System.IO; 4 5public class Program 6{ 7 static List<string> dirList = new List<string>(); //ディレクトリパスリスト 8 static List<string> filePathList = new List<string>(); 9 10 11 /*######################################################## 12 * サブディレクトリを再帰的に取得して設定 13 #########################################################*/ 14 private static void GetSubFolderPathList(string rootPath) 15 { 16 foreach (string path in Directory.GetDirectories(rootPath)) 17 { 18 if (System.IO.Directory.Exists(path) == true) 19 { 20 dirList.Add(path); 21 GetSubFolderPathList(path); 22 } 23 } 24 } 25 26 /*######################################################## 27 * ディレクトリからファイル名を取得 28 #########################################################*/ 29 public static List<string> GetFilePathList(string dirPath) 30 { 31 List<string> list = new List<string>(); 32 foreach (string path in Directory.GetFiles(dirPath)) 33 { 34 //Console.WriteLine("あああ"); 35 list.Add(path); 36 } 37 38 return list; 39 } 40 41 /*######################################################## 42 * 全てのファイルパスを取得 43 #########################################################*/ 44 private static List<string> GetAllFilePath(string rootPath) 45 { 46 GetSubFolderPathList(rootPath); //サブディレクトリー取得 47 48 //Console.WriteLine(" " + dirList.Count()); 49 50 51 List<string> file = new List<string>(); 52 53 if(dirList.Count() == 0) 54 { 55 dirList.Add(rootPath); 56 } 57 58 foreach (string path in dirList) 59 { 60 List<string> list = GetFilePathList(path); 61 file.AddRange(list); 62 } 63 64 return file; 65 } 66 67 static int threadNum = 0; 68 static int threadCount = 0; 69 70 private static async void Run(string filepath) 71 { 72 73 Process process = new Process(); 74 process.StartInfo.FileName = "ffmpeg.exe"; 75 process.EnableRaisingEvents = true; 76 process.StartInfo.CreateNoWindow = true; //コンソール・ウィンドウを開かない 77 process.StartInfo.UseShellExecute = false; //シェル機能を使用しない 78 process.StartInfo.RedirectStandardOutput = true; 79 process.StartInfo.RedirectStandardError = true; 80 81 82 83 string inputPath = filepath; 84 inputPath = "\"" + inputPath + "\""; 85 string outputPath = Path.ChangeExtension(filepath, ".m4a"); 86 outputPath = "\"" + outputPath + "\""; 87 88 //Console.WriteLine("あああ " + Path.ChangeExtension(str, ".m4a")); 89 process.StartInfo.Arguments = " -y -i " + inputPath + " -c:a alac -c:v copy " + outputPath; 90 91 Console.WriteLine(process.StartInfo.Arguments); 92 93 process.Start(); 94 95 //process.WaitForExit(); 96 //threadNum++; 97 Console.WriteLine("ああああ"); 98 99 } 100 101 102 public static void Main() 103 { 104 105 106 string rootPath; 107 Console.WriteLine("input folder path: "); 108 //rootPath = Console.ReadLine().Trim('\"'); 109 rootPath = "C:\\Users\\yw325\\Desktop\\Blooming Days"; 110 111 filePathList = GetAllFilePath(rootPath); //すべてのファイルパスを取得 112 113 // Console.WriteLine("filePathList.Count() " + filePathList.Count()); 114 115 116////////////////////////////////////////////////////////////////////////////////////////////// 117 List<Thread> thread = new List<Thread>(); 118 119 Thread t = new Thread(new ThreadStart(() => 120 { 121 foreach (string str in filePathList) 122 { 123 Run(str); 124 } 125 126 })); 127 128 129 t.Start(); 130 t.Join(); 131////////////////////////////////////////////////////////////////////////////////////////////// 132 Console.WriteLine("終了"); 133 134 135 136 137 } 138 139} 140

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KOZ6.0

2022/07/24 09:53 編集

回答に記載しました。
guest

回答1

0

ベストアンサー

やりたいことは、起動したプロセスがすべて終了するまで待つことでしょうから、Process.Start から Process.WaitForExit を Task としてリスト化し Task.WhenAll でしょう。

プロセスをたくさん起動してしまうと、かえって遅くなるので、セマフォを使って同時に起動するプロセスを制限すると良いと思います。

C#

1static void Main() { 2 // 略 3 using (var slim = new SemaphoreSlim(3)) { // 同時実行数を 3 とします。 4 List<Task> tasks = new List<Task>(); 5 foreach (var str in filePathList) { 6 Task task = Task.Factory.StartNew(() => { Run(slim, str); }); 7 tasks.Add(task); 8 } 9 Task.WhenAll(tasks).Wait(); 10 } 11} 12 13static void Run(SemaphoreSlim slim, string filepath) { 14 slim.Wait(); 15 try { 16 //(略) 17 process.Start(); 18 process.WaitForExit(); 19 20 } finally { 21 slim.Release(); 22 } 23}

投稿2022/07/24 09:52

KOZ6.0

総合スコア2626

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/07/24 10:07 編集

なるほど。ありがとうございます。質問ですが適正なプロセス数はどうやって算出すればいいのでしょうか?
KOZ6.0

2022/07/24 10:13

PC の性能で違ってくるので、デフォルト値を決めておき、パラメタで変更できるようにしておけばいいと思います。
退会済みユーザー

退会済みユーザー

2022/07/24 10:18

ありがとうございます。質問ですがこのアプリは音声ファイルコンバーターなのでマルチスレッドのほうが早くなると思うのですが。その点はどうなのでしょうか?これはマルチプロセスだと思うのですが?
KOZ6.0

2022/07/24 10:35

便乗質問はやめてほしいです。 まぁ、場合による、としかいいようがありません。 たしかにマルチスレッドのほうが起動は軽いですが、1プロセスで使用できるリソースには制限がありますから、動画の編集といった重い処理だと、マルチプロセスで動かしたほうがいい結果が得られるかもしれません。 その辺は観察してみるしかないと思います。
KOZ6.0

2022/07/25 00:38 編集

音声ファイルの変換ソフトに xrecode (https://xrecode.com/) というのがあるんですが、一部の変換を nero や qaac といった exe を起動して行っています。 どのくらいの大きさのファイルをどのくらいの時間で処理できるかの目安になるので是非つかってみてください
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問