是否有可能知道Task Parallel.ForEach处理的当前文件?

时间:2014-04-12 09:44:07

标签: c# .net task

请看这个:

private IEnumerable<string> _source;
public void doWork()
{
    _tokenSource = new CancellationTokenSource();
    var token = _tokenSource.Token;
    Task.Factory.StartNew(() =>
    {
        try
        {
            Parallel.ForEach(_source,
                new ParallelOptions
                {
                    MaxDegreeOfParallelism = _parallelThreads //limit number of parallel threads 
                },
                file =>
                {
                    if (token.IsCancellationRequested)
                        return;
                    //do work...
                });
        }
        catch (Exception)
        { }

    }, _tokenSource.Token).ContinueWith(
            t =>
            {
                //finish...
            }
        , TaskScheduler.FromCurrentSynchronizationContext() //to ContinueWith (update UI) from UI thread
        );
}

此方法收到IEnumerable<string>列表并同时处理我的文件,我想找到一种方法来了解当前处理的文件,我知道我可以使用file变量并启动事件但是我的情况我的列表包含几个重复的文件,这将是一个问题,所以我的问题是,是否有办法知道正在处理的当前列表索引?

2 个答案:

答案 0 :(得分:1)

你说你可以知道当前的字符串,但你可能有重复的问题,然后:

IEnumerable<string>转换为IEnumerable<Tuple<int,string>>以区分重复项。

private IEnumerable<Tuple<int,string>> WithIndecies(IEnumerable<string> _source)
{
      int i =1;
      return _source.Select(x => Tuple.Create(i++, x));
}

用法:

List<string> abc = new List<string>() { "a", "a", "b" };
var res = WithIndecies(abc);

结果:

(1,A)

(2,A)

(3,B)

编辑您的代码:

CancellationTokenSource _tokenSource;
        private IEnumerable<string> _source;
        int _parallelThreads = 10;
        private Tuple<int,String> Currenct_Item;

        public void doWork()
        {
            _tokenSource = new CancellationTokenSource();
            var token = _tokenSource.Token;

            IEnumerable<Tuple<int,string>> _indexed_source = WithIndecies(_source);

            Task.Factory.StartNew(() =>
            {
                try
                {
                    Parallel.ForEach(_indexed_source,
                        new ParallelOptions
                        {
                            MaxDegreeOfParallelism = _parallelThreads //limit number of parallel threads 
                        },
                        file =>
                        {
                            if (token.IsCancellationRequested)
                                return;
                            Currenct_Item = file; // Save CurrentFile and Access it from anywhere else to see current file being processed

                            // file.Item2 is the String so use it in the 'do work'
                            //do work...
                        });
                }
                catch (Exception)
                { }

            }, _tokenSource.Token).ContinueWith(
                    t =>
                    {
                        //finish...
                    }
                , TaskScheduler.FromCurrentSynchronizationContext() //to ContinueWith (update UI) from UI thread
                );
        }

        private IEnumerable<Tuple<int,string>> WithIndecies(IEnumerable<string> _source)
        {
            int i =1;
            return _source.Select(x => Tuple.Create(i++, x));
        }

答案 1 :(得分:1)

如果你只想知道索引,那么有一个重载会产生一个代表索引的int64:

ForEach<TSource>(IEnumerable<TSource>,   ParallelOptions, Action<TSource, ParallelLoopState, Int64>)

来自MSDN:

在IEnumerable上执行带有64位索引的foreach(For Each中的For Each)操作,其中迭代可以并行运行,可以配置循环选项,并且可以监视和操作循环的状态