并行执行问题

时间:2018-06-29 04:29:24

标签: c# task-parallel-library

在这里,我需要对并行任务的执行进行一些了解。

我创建了一个小提琴:

https://dotnetfiddle.net/JO2a4m

我要执行的操作是将几个帐户分批发送到另一种方法,并为每个批次创建一个工作单元(任务),但是当我执行任务时,它只会执行添加的最后一个任务。这是我想打破的想法。

代码:

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

public class Program
{
    public static void Main()
    {
        var accounts = GenerateAccount();
        var accountsProcess = new List<Account>();
        var taskList = new List<Task>();
        var batch = 4;
        var count = 0;
        foreach (var account in accounts)
        {
            if (count == batch)
            {
                taskList.Add(new Task(() => ProcessAccount(accountsProcess)));
                count = 0;
                accountsProcess.Clear();
            }

            count++;
            accountsProcess.Add(account);
        }

        Parallel.ForEach(taskList, t =>
        {
            t.Start();
        }

        );
        Task.WaitAll(taskList.ToArray());
        if (accountsProcess.Count > 0)
            ProcessAccount(accountsProcess);
    }

    public static List<Account> GenerateAccount()
    {
        var accounts = new List<Account>();
        var first = "First";
        var second = "Second";
        for (int i = 0; i <= 1000; i++)
        {
            var account = new Account();
            account.first = first + i;
            account.second = second + i;
            accounts.Add(account);
        }

        return accounts;
    }

    public static void ProcessAccount(List<Account> accounts)
    {
        Console.WriteLine(accounts.Count);
        foreach (var account in accounts)
        {
            Console.WriteLine(account.first + account.second);
        }
    }
}

public class Account
{
    public string first;
    public string second;
}

1 个答案:

答案 0 :(得分:2)

foreach (var account in accounts)
{
    if (count == batch)
    {
        taskList.Add(new Task(() => ProcessAccount(accountsProcess)));
        count = 0;
        accountsProcess.Clear();
    }

    count++;
    accountsProcess.Add(account);
}

问题是所有Task都共享同一个List<Account>对象。

我建议将代码更改为:

foreach (var account in accounts)
{
    if (count == batch)
    {
        var bob = accountsProcess;
        taskList.Add(new Task(() => ProcessAccount(bob)));
        count = 0;
        accountsProcess = new List<Account>();
    }

    count++;
    accountsProcess.Add(account);
}

通过使用bob并将新的List分配给accountsProcess,我们确保每个Task都有自己的List-而不是共享一个{{1 }}。

此外,考虑使用MoreLINQList,而不要自己动手。