Parallel.ForEach迭代中的动作超时

San*_*aza 7 c# task-parallel-library c#-5.0 parallel.foreach

我的代码中有类似的东西:

Parallel.ForEach(myList, new ParallelOptions { MaxDegreeOfParallelism = 4 }, item =>
{
    Process(item);
});
Run Code Online (Sandbox Code Playgroud)

问题是我在Process()方法中做了很多事情(连接到文件共享,解析文件,保存到数据库等),我担心在这个过程中可能会出现问题,使迭代永远不会完成...... 这可能是曾经发生过?

有没有办法为方法设置超时,Process()以避免最终拥有僵尸线程?

更新:

我发现设置超时的最简单方法是在任务上添加毫秒CancellationTokenSource或调用Wait()方法.

选项1

Parallel.ForEach(myList, new ParallelOptions { MaxDegreeOfParallelism = 4 }, item =>
{
    var cts = new CancellationTokenSource(2000);
    Task task = Task.Factory.StartNew(() => Process(item), cts.Token);
});
Run Code Online (Sandbox Code Playgroud)

选项#2

Parallel.ForEach(myList, new ParallelOptions { MaxDegreeOfParallelism = 4 }, item =>
{
    Task task = Task.Factory.StartNew(() => Process(item));
    task.Wait(2000);
});
Run Code Online (Sandbox Code Playgroud)

问题是这些选项都不能取消该Process()方法.我需要检查Process()方法中的某些内容吗?

San*_*aza 3

我最终结合了这两个选项。它有效,但我不知道这是否是执行此操作的正确方法。

解决方案:

        Parallel.ForEach(myList, new ParallelOptions { MaxDegreeOfParallelism = 4 }, item =>
        {
                var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
                var token = tokenSource.Token;

                Task task = Task.Factory.StartNew(() => Process(item, token), token);
                task.Wait();
        });
Run Code Online (Sandbox Code Playgroud)

并在Process()我多次检查取消情况:

    private void Process(MyItem item, CancellationToken token)
    {
        try
        {
            if (token.IsCancellationRequested)
                token.ThrowIfCancellationRequested();

            ...sentences

            if (token.IsCancellationRequested)
                token.ThrowIfCancellationRequested();

            ...more sentences

            if (token.IsCancellationRequested)
                token.ThrowIfCancellationRequested();

            ...etc
        }
        catch(Exception ex)
            Console.WriteLine("Operation cancelled");
Run Code Online (Sandbox Code Playgroud)

  • 对于这个实现,我有很多不喜欢的地方,但强制 ForEach 方法的每次迭代在单独的任务中运行是我发现最丑陋的。 (2认同)