gpt4 book ai didi

c# - 封装一个任务来记录异步函数的持续时间

转载 作者:行者123 更新时间:2023-11-30 14:53:24 27 4
gpt4 key购买 nike

如果我从一个完整的控制台应用开始:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
internal class Program
{
private static void Main(string[] args)
{
var tas = new List<TaskAuditor<string>>();

// I want to await these when they actually run so another thread can use it while
// wait for (example) my EF/SQL to run Async
tas.Add(new TaskAuditor<string>(await GetName(string.Empty, 1)));
tas.Add(new TaskAuditor<string>(await GetName(string.Empty, 2)));

var running = new Task<String>[2];

foreach (var ta in tas)
{
running[0] = ta.Start();
}

var runningCount = tas.Count;

while (runningCount > 0)
{
var idx = Task.WaitAny(running);
runningCount--;

var task = running[idx];

var ta = tas.FirstOrDefault(t => t.Task == task);

Console.WriteLine(ta.Duration.ToString());
}

foreach (var ta in tas)
{
Console.WriteLine(ta.Task.Result);
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}

public async Task<string> GetName(string constr, int id)
{
string result = id.ToString();

// EF/SQL Async goes here
if (string.IsNullOrWhiteSpace(constr))
{
await Task.Delay(1000 * id);
}

return result;
}
}

public class TaskAuditor<T>
{
private Task<T> _task;
private Stopwatch _sw = new Stopwatch();

public TaskAuditor(Task<T> task)
{
_task = task;
}

public Task<T> Start()
{
_sw.Start();
_task.Start();
_sw.Stop();
return _task;
}

public TimeSpan? Duration()
{
TimeSpan? result = null;
if (!_sw.IsRunning)
{
result = _sw.Elapsed;
}
return result;
}

public Task<T> Task
{
get
{
return _task;
}
}
}
}

DotNetFiddle Sample .

问题是我需要等待这个方法,它变成了一个我不太明白的异步噩梦。

最佳答案

首先,您的审核员需要做一些工作。正如我在我的博客上描述的那样,你 can't call Start on a Promise Task .如果要表示导致任务的操作,请使用 Func<Task<T>> .下一个问题是您在任务实际完成之前停止了秒表:

public class TaskAuditor<T>
{
private Func<Task<T>> _func;
private Stopwatch _sw = new Stopwatch();

public TaskAuditor(Func<Task<T>> func)
{
_func = func;
}

public async Task<T> StartAsync()
{
_sw.Start();
try
{
return await _func();
}
finally
{
_sw.Stop();
}
}

public TimeSpan? Duration()
{
TimeSpan? result = null;
if (!_sw.IsRunning)
{
result = _sw.Elapsed;
}
return result;
}
}

接下来,您的调用方法应使用现代便利设施,例如 Task.WhenAll , 以及一个单独的方法来处理它们各自完成的结果,而不是试图将结果从列表中拉出来:

private static async Task<string> ProcessAsync(TaskAuditor<string> auditor)
{
try
{
return await auditor.StartAsync();
}
finally
{
Console.WriteLine(auditor.Duration().ToString());
}
}

private static async Task MainAsync()
{
var tas = new List<TaskAuditor<string>>();
tas.Add(new TaskAuditor<string>(() => GetName(string.Empty, 1)));
tas.Add(new TaskAuditor<string>(() => GetName(string.Empty, 2)));

var running = tas.Select(ta => ProcessAsync(ta));
var results = await Task.WhenAll(running);
foreach (var result in results)
{
Console.WriteLine(result);
}
}

这也使代码保持异步直到它不能异步,即Main。 :

private static void Main()
{
MainAsync().Wait();
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}

关于c# - 封装一个任务来记录异步函数的持续时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29306575/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com