だから私は非同期で何かをするAsyncメソッドを持っています。
private async static void DoSomethingAsync (int i){}
私はそれをループで50回言います。
for (int i = 0; i < 50; i++)
{
DoSomethingAsync (i);
}
ループの終わりに合計処理時間を計算したいので、ストップウォッチを使用しましたが、ループの直後に呼び出されると間違った時間が表示されるので、DoSomethingAsyncが処理を終了するのを待ちません。
doSomethingAsync()の50個のインスタンスすべてが終了するのを待つようにStopwatchに指示する方法。 this の質問を見ましたが、ここではタスクを使用できません。
Taskを使用できない理由はわかりませんが、Mainメソッドなどで呼び出していると思います。だから私はそこから出かけます。
Martin Ullrichが言ったように、タスクを返すためにDoSomethingAsync
メソッドを変更します。
private async static Task DoSomethingAsync(int i)
{
...
}
次に、メソッドをList<Task>
に追加して、ループを実行する新しいメソッドを作成します。
private static async void PerformLoop()
{
Stopwatch timer = new Stopwatch();
timer.Start();
List<Task> l = new List<Task>();
for (int i = 0; i < 50; i++)
{
l.Add(DoSomethingAsync(i));
}
await Task.WhenAll(l);
timer.Stop();
Console.WriteLine(timer.Elapsed.TotalSeconds);
}
以前にループを実行した場所から、この場合はMain
メソッドが新しいメソッド呼び出しをそこに追加するだけです。
static void Main(string[] args)
{
PerformLoop();
Console.ReadLine();
}
これは、async void
を使用することの欠点です。呼び出されたメソッドを変更せずにこれを行う方法はありません(コールバックを呼び出したり、ミューテックスのロックを解除したりできるようにするため)。
代わりにasync Task
を返すようにメソッドを変更し、待機せずにこのメソッドを呼び出すだけの別のメソッドを作成して、以前にasync void
署名が必要だった場所で使用できます。
async void
なぜですか?そうしないでください。asnyc Task
、またはActionBlock
sまたはParallelFor/ForEach
を使用してください。ただし、純粋に目新しさのために(そして真のゲージとして使用されないように)、並列プロセスIDで時間を計算する場合は、並列メソッド内にタイマーを配置し、グローバル変数を使用して Interlocked.Addメソッドを使用することを検討してください) スレッドセーフの方法
private long CombinedMs;
...
private async static void DoSomethingAsync (int i)
{
var sw = new StopWatch();
sw.Start();
...
sw.Stop();
Interlocked.Add(ref CombinedMs,sw.ElapsedMillisecond);
}
とにかく、私はあなたが仕事で画板に戻る必要があると思います...頑張ってください
このような、消費された時間を追跡するためのグローバルカウンターを持つことができます。
public class YourClass
{
TimeSpan tSpan;
public void PerformOp()
{
tSpan=new TimeSpan();
for (int i = 0; i < 50; i++)
{
DoSomethingAsync (i);
}
}
private async static void DoSomethingAsync (int i)
{
Stopwatch stp = new StopWatch();
stp.Start();
//your Operation here
stp.Stop();
tSpan+=stp.Elapsed;//not the exact systax or usage but you get the idea
}
}