异步任务划分工作量

时间:2013-09-03 01:39:02

标签: c# multithreading c#-4.0 task-parallel-library

我试图根据id范围划分多个任务之间的工作 我有这个方法,基于i获取开始和结束范围。 我可以看到GetRanges方法正在将范围正确划分为任务。 但是当任务被称为StartWork(startRange,endRange)时,它有时会将所有任务设置为相同的范围 有时有2或3个重复范围。 异步任务启动时,基本上没有传递唯一的startrange和endRange?我该如何解决?

        int endRange = 0;
        int startRange = 0;
        int total = GetTotal();
        int startIndex =1;
        for (int i = 0; i < taskCount; i++)
        {
            GetRanges(ref startRange, ref endRange, total, i, startIndex);             
            Console.WriteLine("startRange {0} EndRange {1}", startRange, endRange);             
            tasks[i] = Task.Factory.StartNew(() => StartWork(startRange, endRange));

        }

        private void StartWork(int startRange, int endRange)
        {
            Console.WriteLine("Thread {0}  task startRange {1} EndRange {2}", System.Threading.Thread.CurrentThread.ManagedThreadId, startRange, endRange);
        }

        private void GetRanges(ref int startRange, ref int endRange, int total, int threadIndex, int startIndex)
        {
            int averagetask = (total - startIndex) / taskCount;
            startRange = (averagetask * threadIndex) + 1;

            if (threadIndex == taskCount - 1)
            endRange = total;
            else
            endRange = averagetask * (threadIndex + 1);

        }

这是输出 startRange 1 EndRange 785761 startRange 785762 EndRange 1571522 startRange 1571523 EndRange 2357283 startRange 2357284 EndRange 3143047

线程3任务startRange 2357284 EndRange 3143047 线程5任务startRange 2357284 EndRange 3143047 线程4任务startRange 2357284 EndRange 3143047 线程6任务startRange 2357284 EndRange 3143047

1 个答案:

答案 0 :(得分:1)

小心使用ref参数并将它们传递给不同线程上的任务。我认为发生的事情是在任务查看该值时,它已经在另一个线程上被更改了。即你的StartWork方法正在查看startRange / endRange的当前值,该值不断被更改。

尝试这样做:

for (int i = 0; i < taskCount; i++)
{
    GetRanges(ref startRange, ref endRange, total, i, startIndex);             
    Console.WriteLine("startRange {0} EndRange {1}", startRange, endRange);             
    var tempStartRange = startRange;
    var tempEndRange = endRange;
    tasks[i] = Task.Factory.StartNew(() => StartWork(tempStartRange, tempEndRange));
}