BackgroundWorker或Task.WhenAll

时间:2018-03-27 11:44:14

标签: c# multithreading backgroundworker

我现在正在使用后台服务来处理耗时的操作,同时显示UI中的进度

但是现在正在寻找一些时间方面的性能改进[因为目前后台员工需要更多时间来完成处理]

Do_Work在后台工作程序中的当前解决方案就像

foreach(string _entry in ArrayList){

  //process the _entry(communicate to a service and store response in Db) and took almost 2-3 seconds for the completion
}

ArrayList包含近25000条记录。因此,现在需要几乎25000 * 3 = 75000秒的时间进行处理

我想到的新解决方案就像是同时启动每个500项的50个线程并等待完成所有类似的线程

int failed = 0;
var tasks = new List<Task>();            
for (int i = 1; i < 50; i++)
{
    tasks.Add(Task.Run(() =>
    {

        try
        {
            //Process 500 items from Array .(communicate to a service and store response in Db)
        }
        catch
        {
            Interlocked.Increment(ref failed);
            throw;
        }
    }));
}
Task t = Task.WhenAll(tasks);    //Runs 50 Threads         
try
{
    await t;
}
catch (AggregateException exc)
{
string _error="";
    foreach (Exception ed in t.Exception.InnerExceptions)
    {
       _error+=ed.Message;
    }
     MessageBox.Show(_error);
}
if (t.Status == TaskStatus.RanToCompletion)
    MessageBox.Show("All ping attempts succeeded.");
else if (t.Status == TaskStatus.Faulted)
    MessageBox.Show("{0} ping attempts failed", failed.ToString());

这有助于缩短处理时间吗?还是一些更好的方法? 我尝试使用10的小样本并进行调试,但我看不出太大的区别(我在选择WhenAll时出了什么问题?)

2 个答案:

答案 0 :(得分:1)

您需要一次处理少量记录。

处理n个不同任务的记录。假设n = 5.所以5个不同的任务t1,t2,t3,t4和t5。一旦任何人完成一行处理数据,他们应该开始处理t(1 + n),t(2 + n),t(3 + n),t(4 + n),t(5 + n)行等等直到处理完所有记录。

将所有处理过的值存储到字典或列表中,以确定哪一个属于哪个记录。

这就像递归函数。

我过去曾使用过这种方法,它确实提高了性能。您可以根据PC配置微调n的值

答案 1 :(得分:-1)

我建议尝试使用BlockingCollection