1

我试图根据 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

4

1 回答 1

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));
}
于 2013-09-03T02:52:40.977 回答