Gurmeet
Gurmeet

Reputation: 3314

Check time taken by a thread inside Parallel.Foreach and exit if it is taking more time

I have code with Parallel.Foreach which is processing files and doing some operation on each file in parallel.

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

I want to skip a file and move to next file (but don't want to exit the Parallel.Foreach) if a particular file is taking too long (say 2 mins). Is there any way in Parallel.Foreach to check the time taken by thread to process a single file.

Thanks

Upvotes: 0

Views: 325

Answers (1)

Enigmativity
Enigmativity

Reputation: 117124

I'd suggest you don't use Parallel.ForEach and instead use Mirosoft's extremely more powerful Reactive Framework. Then you can do this:

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 */
        })

This is all done in parallel. The Observable.Amb operator starts the two observables defined in its argument list and takes the value from which ever of the two produces a value first - if it's the Start observable it has processed your file and if it's the Timer observable then 2.0 minutes has elapsed without a result from the file.

If you want to stop the processing when it is half-way through then just call subscription.Dispose().

Use NuGet "System.Reactive" to get the bits.


The query in lambda form as per request in comments:

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 });

Upvotes: 1

Related Questions