【问题标题】:Check time taken by a thread inside Parallel.Foreach and exit if it is taking more time检查 Parallel.Foreach 中的线程花费的时间,如果花费更多时间则退出
【发布时间】:2017-11-24 04:42:56
【问题描述】:

我有 Parallel.Foreach 的代码,它正在处理文件并对每个文件并行执行一些操作。

Parallel.ForEach(lstFiles, file=>
{
 // Doing some operation on file
 // Skip file and move to next if it is taking too long
});

我想跳过一个文件并移动到下一个文件(但不想退出 Parallel.Foreach),如果特定文件花费的时间太长(比如 2 分钟)。 Parallel.Foreach 有什么方法可以检查线程处理单个文件所花费的时间。

谢谢

【问题讨论】:

  • 您可以在 foreach 块中等待一个任务,并等待 stackoverflow.com/questions/4238345/… 中显示的 WhenAny like 的任务。
  • I want to skip a file and move to next file - 这个说法令人困惑。 Parallel.ForEach 正在并行处理列表中的所有文件,而不是一次处理 1 个。如果您决定停止处理特定文件,这就是您需要做的一切。其他人将继续同时进行。

标签: c# multithreading task-parallel-library parallel.foreach


【解决方案1】:

我建议您不要使用Parallel.ForEach,而是使用 Mirosoft 极其强大的响应式框架。然后你可以这样做:

var query =
    from file in lstFiles.ToObservable()
    from result in Observable.Amb(
        Observable.Start(() => SomeOperation(file)).Select(_ => true),
        Observable.Timer(TimeSpan.FromMinutes(2.0)).Select(_ => false))
    select new { file, result };

IDisposable subscription =
    query
        .Subscribe(x =>
        {
            /* do something with each `new { file, result }`
               as they arrive. */
        }, ex =>
        {
            /* do something if an error is encountered */
            /* (stops processing on first error) */
        }, () =>
        {
            /* do something if they have all finished successfully */
        })

这一切都是并行完成的。 Observable.Amb 运算符启动在其参数列表中定义的两个可观察对象,并获取两者中的任何一个首先产生值的值 - 如果是 Start 可观察对象,它已经处理了您的文件,如果是 Timer 可观察对象,那么2.0 分钟过去了,文件没有结果。

如果您想在处理到一半时停止处理,只需致电subscription.Dispose()

使用 NuGet "System.Reactive" 获取位。


根据 cmets 中的请求以 lambda 形式查询:

var query =
    lstFiles
        .ToObservable()
        .SelectMany(
            file =>
                Observable.Amb(
                    Observable.Start(() => SomeOperation(file)).Select(_ => true),
                    Observable.Timer(TimeSpan.FromMinutes(2.0)).Select(_ => false)),
            (file, result) => new { file, result });

【讨论】:

  • 您能否也以 Lambda 形式添加您的 linq 查询“var query = from file in lstFiles.ToObservable()”?
  • @Gerry - 我已经为查询添加了 lambda 表单。
  • 非常感谢@Enigmativity。
  • Amb 会并行处理文件(如parallel.foreach)还是我需要明确处理?
  • @Gerry - .Amb 启动传递给它的两个可观察对象并返回第一个以产生值。它并行执行每个操作。但正是.SelectMany 导致每个lstFiles 被并行处理。一切都为您完成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-20
  • 2014-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
相关资源
最近更新 更多