it-roy-ru.com

как рассчитать время выполнения асинхронного метода в C #

Итак, у меня есть метод Async, который делает что-то асинхронно.

private async static void DoSomethingAsync (int i){}

Я называю это в цикле, скажем, 50 раз.

for (int i = 0; i < 50; i++)
 {
    DoSomethingAsync (i);
 }

В конце цикла я хочу вычислить общее время обработки, я использовал секундомер, но, как вы можете себе представить, он дает мне неправильное время, так как он вызывается сразу после цикла, он не ждет, пока DoSomethingAsync завершит обработку. 

как заставить секундомер ждать завершения всех 50 экземпляров DoSomethingAsync (). Я видел это вопрос, но я не могу использовать Задачу здесь.

5
ahsant

Я не знаю, почему вы не можете использовать Task, я предполагаю, что вы вызываете его в методе Main или как-то еще. Так что я выйду из этого.

Как сказал Мартин Уллрих, я бы изменил метод 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();
}
4
Mike

Это недостаток использования async void. Нет способа сделать это без изменения вызываемого метода (чтобы он мог вызывать обратный вызов, разблокировать мьютекс и т.д.).

Вместо этого вы можете изменить свой метод, чтобы он возвращал async Task, и создать другой метод, который просто вызывает этот метод без ожидания, который затем можно использовать в местах, для которых ранее требовалась подпись async void.

4
Martin Ullrich

async void почему? не делайте этого, используйте asnyc Task или ActionBlocks или ParallelFor/ForEach. Однако исключительно для новизны (и не для использования в качестве истинного измерителя), если вы хотите рассчитать время в идентификаторе параллельного процесса, рассмотрите возможность помещения таймера в свой параллельный метод и использования глобальной переменной и используйте Interlocked.Add Method Метод безопасности нитей

private long CombinedMs;

...

private async static void DoSomethingAsync (int i)
{

   var sw = new StopWatch();
   sw.Start();
   ...
   sw.Stop();

   Interlocked.Add(ref CombinedMs,sw.ElapsedMillisecond);

}

Во всяком случае, я думаю, что вам нужно вернуться к чертежной доске на задания ... Удачи

2
Michael Randall

Вы можете иметь глобальный счетчик для отслеживания потребляемого времени, что-то вроде этого. 

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 
}

}
0
Dharani Kumar