【问题标题】:C# - Looping won't stop (each iteration starts new Task)C# - 循环不会停止(每次迭代都会启动新任务)
【发布时间】:2026-01-10 04:45:01
【问题描述】:

所以我对以下餐饮哲学家的问题有一个基本的解决方案:

using System;
using System.Threading.Tasks;

namespace Conductor
{
    class Program
    {
        private static object _locker = new object();

        static void Main(string[] args)
        { 
            object[] sticks = {new object(),
                               new object(),
                               new object(),
                               new object(),
                               new object()};

            for (int i = 0; i<5; i++)
            {
                int next = (i + 1) % 5;
                Task.Factory.StartNew(() => Eat(sticks[i], sticks[next], i)); 
            }
        }

        static void Eat(object _leftChopstick, object _rightChopstick, int i)
        {
            lock (_locker)
            {
                lock (_leftChopstick)
                {
                    lock (_rightChopstick)
                    {
                        Console.WriteLine("Eating" + i);
                    }
                }
            }
        }
    }
}

虽然它可能不是最有效的解决方案,但当 i 设置为 5 时,它会在“StartNew”调用中引发 IndexOutOfRange 异常。我无法弄清楚使用任务工厂如何以某种方式使我的程序忽略了 for 循环健康)状况。

如果我运行这段代码,那很好:

using System;
using System.Threading.Tasks;

namespace Conductor
{
    class Program
    {
        private static object _locker = new object();

        static void Main(string[] args)
        { 
            object[] sticks = { new object(),
                               new object(),
                               new object(),
                               new object(),
                               new object()};

            int i = 0;
            Task.Factory.StartNew(() => Eat(sticks[i], sticks[i + 1], i));
            Task.Factory.StartNew(() => Eat(sticks[i+1], sticks[i + 2], i + 1));
            Task.Factory.StartNew(() => Eat(sticks[i+2], sticks[i + 3], i + 2));
            Task.Factory.StartNew(() => Eat(sticks[i+3], sticks[i + 4], i + 3));
            Task.Factory.StartNew(() => Eat(sticks[i + 4], sticks[0], i + 4));
            Console.ReadLine();
        }

        static void Eat(object _leftChopstick, object _rightChopstick, int i)
        {
            lock (_locker)
            {
                lock (_leftChopstick)
                {
                    lock (_rightChopstick)
                    {
                        Console.WriteLine("Eating" + i);
                    }
                }
            }
        }
    }
}

另外,如果我通过循环进行调试,我会得到同样的异常。

对此的任何帮助将不胜感激。抱歉,如果它太基本或者我的代码中存在一些我错过的微不足道的缺陷。谢谢。

【问题讨论】:

  • 使用调试器并单步执行代码。不要只是 CODE AND GO 意味着编写代码并启动预期会出现 Zero 错误的应用程序。
  • 是的,我也这样做了。我已经编辑了我的答案来说明这一点。无论如何,干杯。

标签: c# multithreading for-loop task-parallel-library


【解决方案1】:
for (int i = 0; i < 5; i++)
            {
                int j = i;
                int next = (i + 1) % 5;
                Task.Factory.StartNew(() => Eat(sticks[j], sticks[next], j));
            }

【讨论】:

  • 问题出在涉及Task.Factory时对i的引用范围变化。通过将局部变量分配给仅由单个目标进程使用,您可以避免更高范围的变量被外部因素修改的风险。
最近更新 更多