私は最高の解決策を見つけるためにあなたの助けが必要です。これは私の元のコードです:いつ多くの仕事に全部
ファイルを行で読み込み、各行をタスクで処理します。しかし、ファイルの行数が100万行以上の場合、タスクの配列は大きくなりますが、このコードはまだ有効ですか?別の解決策を見つけるべきです。私を助けてください。ありがとう。
私は最高の解決策を見つけるためにあなたの助けが必要です。これは私の元のコードです:いつ多くの仕事に全部
ファイルを行で読み込み、各行をタスクで処理します。しかし、ファイルの行数が100万行以上の場合、タスクの配列は大きくなりますが、このコードはまだ有効ですか?別の解決策を見つけるべきです。私を助けてください。ありがとう。
これは悪い考えです。それはあまりにも多くのスレッドを起動する可能性があります。これを行うには
Aはるかに優れた方法は、単にそのようParallel.ForEach()
を使用することです。しかしこれは、非同期/のawait使用していません
using System;
using System.IO;
using System.Threading.Tasks;
namespace Demo
{
static class Program
{
static void Main()
{
string filename = @"Your test filename goes here";
Parallel.ForEach(File.ReadLines(filename), process);
}
private static void process(string line)
{
Console.WriteLine(line);
}
}
}
。しかし、あなたが望むなら、あなたは仕事の中でParallel.ForEach()
への全体の呼び出しを包むことができます。
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
namespace Demo
{
static class Program
{
static void Main()
{
Task.Run(test).Wait();
}
static async Task test()
{
string filename = @"Your filename goes here";
await processFile(filename);
}
static async Task processFile(string filename)
{
var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 8, BoundedCapacity = 100 };
var action = new ActionBlock<string>(s => process(s), options);
foreach (var line in File.ReadLines(filename))
await action.SendAsync(line);
action.Complete();
await action.Completion;
}
static void process(string line)
{
Thread.Sleep(100); // Simulate work.
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " " + line);
}
}
}
これはあなたにasync
サポートを提供します:あなたはTask Parallel Library(マイクロソフトNuGetパッケージ)を使用したい場合は
また、あなたはこのような何かを行うことができます。
補遺:スレッドプールの調整のデモ。
(これはシェイに応答する__さんのコメント。)
タスクがそう秒またはよりも実行に時間がかかり、長時間実行タスクの多くを開始した場合は、スロットリングのThreadPool表示される場合があります。
これは、現在のプロセスのスレッドプールスレッドの数が、ThreadPool.GetMinThreads(out workers, out ports);
への呼び出しによって返されたworker
の数に等しいかそれを超える場合に発生します。
この場合、新しいスレッドプールスレッドの起動は、新しいスレッドプールスレッドが作成されるまで少し時間がかかります(システムで1秒遅れます)。多くの場合、別のスレッドプールスレッドを使用できるようになり、そのスレッドプールが代わりに使用されます(もちろん、スロットルの制限は です)。
次のコードは、問題を示しています。最初の8つのスレッドは非常に迅速に開始するが、その後、新しいスレッドが絞られているか
Min workers = 8
Thread 3 started at time 00:00:00.0098651
Thread 6 started at time 00:00:00.0098651
Thread 8 started at time 00:00:00.0099841
Thread 5 started at time 00:00:00.0099680
Thread 7 started at time 00:00:00.0099918
Thread 4 started at time 00:00:00.0098739
Thread 10 started at time 00:00:00.0100828
Thread 9 started at time 00:00:00.0101833
Thread 11 started at time 00:00:01.0096247
Thread 12 started at time 00:00:02.0098105
Thread 13 started at time 00:00:03.0099824
Thread 14 started at time 00:00:04.0100671
Thread 15 started at time 00:00:05.0098035
Thread 16 started at time 00:00:06.0099449
Thread 17 started at time 00:00:07.0096293
Thread 18 started at time 00:00:08.0106774
Thread 19 started at time 00:00:09.0098193
Thread 20 started at time 00:00:10.0104156
Thread 3 started at time 00:00:10.0109315
Thread 8 started at time 00:00:10.0112171
Thread 7 started at time 00:00:10.0112531
Thread 9 started at time 00:00:10.0117256
Thread 4 started at time 00:00:10.0117920
Thread 10 started at time 00:00:10.0117298
Thread 6 started at time 00:00:10.0109381
Thread 5 started at time 00:00:10.0112276
Thread 21 started at time 00:00:11.0095859
Thread 11 started at time 00:00:11.0101189
Thread 22 started at time 00:00:12.0095421
Thread 12 started at time 00:00:12.0111173
Thread 23 started at time 00:00:13.0095932 ...
注:私のシステムで
int workers, ports;
ThreadPool.GetMinThreads(out workers, out ports);
Console.WriteLine("Min workers = " + workers); // Prints 8 on my system.
var sw = Stopwatch.StartNew();
for (int i = 0; i < 100; ++i)
{
Task.Run(() =>
{
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} started at time {sw.Elapsed}");
Thread.Sleep(10000);
});
}
Console.ReadLine();
、これは次のように出力しますスレッドの最初のバッチが終了してから再利用できるまで、毎秒約1回までです。
このエフェクトは、スレッドの終了に比較的長い時間がかかる場合にのみ発生します。
ニース。どうもありがとう。 –
"それはあまりにも多くのスレッドを起動する" - 私はそれが本当であるか分からない。あなたは詳しく説明できますか? –
@shay__ファイルの各行に対して 'Task.Run()'を呼び出すと、1行に1つのスレッドを起動しようとします。いくつかのスレッドの後に、スレッドごとに0.5秒の遅延が導入されます。単純なテストでは、新しいスレッドが作成され再利用される前に前のスレッドが終了するため、多数のスレッドを作成できません。しかし、各行の処理が十分に遅い場合、スレッドの数は増加し続けるでしょう。 –
[CodeReview](http://codereview.stackexchange.com)に属しているため、このトピックを議論の対象外としています。 –
TPLは内部でスレッドプールを使用しているため、100万スレッドを開始しません。タスクのパフォーマンスがどのように動作するかは不明です。 8つのコア(コアの数)を起動し、それらの8つのタスクの間で線を分割すると、パフォーマンスが向上する可能性があります。 – Domysee
@YuvalItzchakovコードレビューではありません。問題を理解するコードを与えることは、多くの単語を書くことよりも優れています。私が必要とするのは、私の問題を解決するためのあなたの助けです。ありがとう。 –