複数のバックグラウンド ワーカーが 5 秒間実行中のプロセスのタスクよりも優れたパフォーマンスを発揮するという変更はありますか? タスクは短時間実行プロセス用に設計されているという本を読んだことを覚えています。
私が尋ねる理由はこれです:
完了するのに 5 秒かかるプロセスがあり、完了するまでに 4000 のプロセスがあります。最初に私はしました:
for (int i=0; i<4000; i++) {
Task.Factory.StartNewTask(action);
}
そして、これはパフォーマンスが低下しました (最初の 1 分後、3 ~ 4 個のタスクが完了し、コンソール アプリケーションには 35 個のスレッドがありました)。これはばかげているのかもしれませんが、スレッドプールはこの種の状況を処理すると思いました (すべてのアクションをキューに入れ、スレッドが空いたらアクションを実行します)。
2 番目のステップは、手動で Environment.ProcessorCount バックグラウンド ワーカーを実行し、すべてのアクションを ConcurentQueue に配置することでした。したがって、コードは次のようになります。
var workers = new List<BackgroundWorker>();
//initialize workers
workers.ForEach((bk) =>
{
bk.DoWork += (s, e) =>
{
while (toDoActions.Count > 0)
{
Action a;
if (toDoActions.TryDequeue(out a))
{
a();
}
}
}
bk.RunWorkerAsync();
});
これははるかに優れたパフォーマンスを発揮しました。30 人のバックグラウンド ワーカー (最初のケースと同じ数のタスク) があった場合でも、タスクよりもはるかに優れたパフォーマンスを発揮しました。
ル:
次のようにタスクを開始します。
public static Task IndexFile(string file)
{
Action<object> indexAction = new Action<object>((f) =>
{
Index((string)f);
});
return Task.Factory.StartNew(indexAction, file);
}
Index メソッドは次のとおりです。
private static void Index(string file)
{
AudioDetectionServiceReference.AudioDetectionServiceClient client = new AudioDetectionServiceReference.AudioDetectionServiceClient();
client.IndexCompleted += (s, e) =>
{
if (e.Error != null)
{
if (FileError != null)
{
FileError(client,
new FileIndexErrorEventArgs((string)e.UserState, e.Error));
}
}
else
{
if (FileIndexed != null)
{
FileIndexed(client, new FileIndexedEventArgs((string)e.UserState));
}
}
};
using (IAudio proxy = new BassProxy())
{
List<int> max = new List<int>();
if (proxy.ReadFFTData(file, out max))
{
while (max.Count > 0 && max.First() == 0)
{
max.RemoveAt(0);
}
while (max.Count > 0 && max.Last() == 0)
{
max.RemoveAt(max.Count - 1);
}
client.IndexAsync(max.ToArray(), file, file);
}
else
{
throw new CouldNotIndexException(file, "The audio proxy did not return any data for this file.");
}
}
}
このメソッドは、Bass.net ライブラリを使用して、mp3 ファイルからデータを読み取ります。次に、非同期メソッドを使用して、そのデータを WCF サービスに送信します。タスクを作成する IndexFile(string file) メソッドは、for ループで 4000 回呼び出されます。FileIndexed と FileError の 2 つのイベントは処理されないため、スローされることはありません。