に多くのタスクを実行する場合:C#のスレッドを単一のスレッド上で、私はこれを行う、場合どうなりますかTask.WhenAll
await Task.WhenAll(items.select(x => SomeAsyncMethod(x)))
// Where SomeAsyncMethod is defined like this (writeAsync is pure async io)
async Task SomeAsyncMethod(Item item){
await myDevice.writeAsync(...).ConfigureAwait(false);
//do some cpu intensive stuff...
}
をしてitems
で10.000の項目があると言います。 SomeAsyncMethod
のそれぞれが待ってから続けると、スレッドプールのスレッド上で実行されます。だからSomeAsyncsMethod
の多くが返ってくると、スレッドプールからの複数のスレッドが同時に取得されるか、この場合にはいつでも1つのスレッドだけがSomeAsyncMethod
に "do some CPU intensive stuff"を実行しますか?
更新:ここにサンプルプログラムがあります。 8つの論理コアを持つPCでこれをテストすると、minthreadsは12または13で、maxthreadsは35-40の範囲で終了します。 したがって、最大4つのスレッドが論理コアとして作成されるように見えます。 10.000または100.000ファイルが作成されても問題はありません。同じ最大スレッド数が使用されています。これは、すべてのタスクがファイルシステムへのアクセスを待っているためですか?このプログラムは、Cに小さなファイルの多くを作成することに、注意してください:\ TMP \はasynctest:今、私はそれぞれ同時にaysnc IOタスクの多くを行う複数のスレッドを起動した場合
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication4 {
internal class Program {
private static void Main(string[] args) {
var myDevice = new MyDevice();
var ints = new List<int>();
for (var i = 0; i < 10000; i++) {
ints.Add(i);
}
var task = Task.WhenAll(ints.Select(i => myDevice.WriteTextAsync(i.ToString())));
task.Wait();
Console.WriteLine("Max thread count = " + myDevice.MaxThreadCount);
Console.WriteLine("Min thread count = " + myDevice.MinThreadCount);
Console.ReadLine();
}
}
public class MyDevice {
public ConcurrentDictionary<string, string> ThreadIds;
public int MaxThreadCount;
public int MinThreadCount = Process.GetCurrentProcess().Threads.Count;
public async Task WriteTextAsync(string text) {
var filePath = @"c:\tmp\asynctest\" + text + ".txt";
var encodedText = Encoding.Unicode.GetBytes(text);
using (var sourceStream = new FileStream(filePath,
FileMode.Append, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true)) {
await sourceStream.WriteAsync(encodedText, 0, encodedText.Length).ConfigureAwait(false);
MaxThreadCount = Math.Max(MaxThreadCount, Process.GetCurrentProcess().Threads.Count);
MinThreadCount = Math.Min(MinThreadCount, Process.GetCurrentProcess().Threads.Count);
}
}
}
}
更新2.、それはしていません私が実行したばかりのテストでは、10.000個のファイルがそれぞれ4つのスレッドで作成された後、最大スレッドは41、最小スレッドは12だったようです。非同期タスクの継続に使用されるスレッドの数を集中管理することができます。ここでは4つのスレッドが10.000非同期操作のそれぞれを開始します例です。
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication4 {
internal class Program {
private static void Main(string[] args) {
var myDevice = new MyDevice();
var ints = new List<int>();
const int limit = 10000;
for (var i = 0; i < limit; i++) {
ints.Add(i);
}
List<Task> jobs = new List<Task>();
for (var j = 0; j < 4*limit; j+=limit) {
var jobid = j;
jobs.Add(Task.Run(() => Runjob(ints, myDevice, jobid)));
}
Task.WaitAll(jobs.ToArray());
Console.WriteLine("Max thread count = " + myDevice.MaxThreadCount);
Console.WriteLine("Min thread count = " + myDevice.MinThreadCount);
Console.ReadLine();
}
private static void Runjob(List<int> ints, MyDevice myDevice, int jobid) {
Console.WriteLine("Starting job " + jobid);
var task = Task.WhenAll(ints.Select(i => myDevice.WriteTextAsync((jobid+i).ToString())));
task.Wait();
Console.WriteLine("Finished job " + jobid);
}
}
public class MyDevice {
public int MaxThreadCount;
public int MinThreadCount = Process.GetCurrentProcess().Threads.Count;
public async Task WriteTextAsync(string text) {
var filePath = @"c:\tmp\asynctest\" + text + ".txt";
var encodedText = Encoding.Unicode.GetBytes(text);
using (var sourceStream = new FileStream(filePath,
FileMode.Append, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true)) {
await sourceStream.WriteAsync(encodedText, 0, encodedText.Length).ConfigureAwait(false);
MaxThreadCount = Math.Max(MaxThreadCount, Process.GetCurrentProcess().Threads.Count);
MinThreadCount = Math.Min(MinThreadCount, Process.GetCurrentProcess().Threads.Count);
}
}
}
}
すべてに依存します。 SynchronisationContext。 –
最も簡単な方法は、試してみることです。 Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);を追加して見つけてください。 –
さて、私はConfigureAwaitをfalseにして、コンテキストが必要ではないと言うことができます(私はこれを再考するために今質問を編集します)。 –