使用任务工厂存储每个任务的任务完成时间

时间:2015-04-16 07:23:27

标签: c# multithreading

我正在使用任务工厂生成并行线程,我的代码如下所示。我有要求打印每个线程的完成时间,但不知道如何检查每个线程。目前我的代码正在等待所有任务完成,然后计算时间。

stp1.Start();
        for (int i = 0; i < tsk.Length; i++)
        {
            tsk[i] = Task.Factory.StartNew((object obj) =>
            {
                resp = http.SynchronousRequest(web, 443, true, req);
            }, i);
        }
        try
        {
            Task.WaitAll(tsk);
        }
        stp1.Stop();

2 个答案:

答案 0 :(得分:7)

您可以向Task添加续集。延续是一种在给定的Task完成时将被调用的方法。

for (int i = 0; i < tsk.Length; i++)
{
    tsk[i] = Task.Factory.StartNew((object obj) =>
    {
        resp = http.SynchronousRequest(web, 443, true, req);
    }, i);

    tsk[i].ContinueWith(antecedent=> 
    {
        //antecedent is completed
        //Do whatever here                
    });
}

如果您需要计时个别任务,每个任务需要一个秒表。您可以在StopWatch内启动StartNew并在ContinueWith中停止。

如果这是您的实际代码,您可以简单地计算您调用的同步操作(在本例中为http.SynchronousRequest)。例如,以下代码就足够了。

for (int i = 0; i < tsk.Length; i++)
{
    tsk[i] = Task.Factory.StartNew((object obj) =>
    {
        StopWatch watch = StopWatch.StartNew();

        resp = http.SynchronousRequest(web, 443, true, req);

        watch.Stop();
        Console.WriteLine(watch.Elapsed);
    }, i);
}

顺便说一下,网络操作本质上是异步的;将提供异步API,您可以使用它而不是在Task中包装同步Web请求。例如,也许HttpClient.SendAsync

答案 1 :(得分:1)

我首先要说你不需要线程池线程来执行异步IO绑定操作。例如,不使用Task.Factory.StartNew,而是使用自然异步的API,例如一个HttpClient商品。

然后,我说你可以使用Task.WhenAny在完成每项任务时等待:

// Note I'm assuming some kind of async implementation which returns a Task<T>
var tasks = tsk.Select(req => http.AsyncRequest(web, 443, true, req));

while (tasks.Count > 0)
{
    var finishedTask = await Task.WhenAny(tasks);
    // Do something with finishedTask

    tasks.Remove(finishedTask);
}