首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Parallel.ForEach用例

Parallel.ForEach用例
EN

Stack Overflow用户
提问于 2022-07-16 12:23:33
回答 2查看 129关注 0票数 3

我想知道我是否应该在我的案例中使用Parallel.ForEach()。关于一些上下文:我正在使用NAudio库开发一个小型音乐播放器。我希望在工厂方法中使用Parallel.ForEach()来快速访问.mp3文件并创建TrackModel对象来表示它们(大约400个)。代码如下所示:

代码语言:javascript
复制
public static List<TrackModel> CreateTracks(string[] files)
{
    // Guard Clause
    if (files == null || files.Length == 0) throw new ArgumentException();

    var output = new List<TrackModel>();

    TrackModel track;

    Parallel.ForEach(files, file =>
    {
        using (MusicPlayer musicPlayer = new MusicPlayer(file, 0f))
        {
             track = new TrackModel()
             {
                 FilePath = file,
                 Title = File.Create(file).Tag.Title,
                 Artist = File.Create(file).Tag.FirstPerformer,
                 TrackLength = musicPlayer.GetLengthInSeconds(),
             };
         }

         lock (output)
         {
             output.Add(track);
         }
   });

   return output;
}

注意:我使用lock防止多个线程同时向列表中添加元素。

我的问题是:在这种情况下我应该使用Parallel.ForEach()还是编写一个普通的foreach循环更好?这是实现更好性能的正确方法吗?我应该首先结合使用多线程和文件访问吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-07-17 04:10:20

最好同时避免foreachParallel.ForEach。在这种情况下,AsParallel()是你的朋友。

试试这个:

代码语言:javascript
复制
public static List<TrackModel> CreateTracks(string[] files)
{
    if (files == null || files.Length == 0) throw new ArgumentException();

    return
        files
            .AsParallel()
            .AsOrdered()
            .WithDegreeOfParallelism(2)
            .Select(file =>
            {
                using (MusicPlayer musicPlayer = new MusicPlayer(file, 0f))
                {
                    return new TrackModel()
                    {
                        FilePath = file,
                        Title = File.Create(file).Tag.Title,
                        Artist = File.Create(file).Tag.FirstPerformer,
                        TrackLength = musicPlayer.GetLengthInSeconds(),
                    };
                }
            })
            .ToList();
}

这将为您处理所有并行逻辑和幕后锁定。

票数 4
EN

Stack Overflow用户

发布于 2022-07-17 12:04:52

结合来自评论和答案的建议并根据我的代码进行调整,我能够用以下代码解决我的问题:

代码语言:javascript
复制
public List<TrackModel> CreateTracks(string[] files) 
{
    var output = files
                     .AsParallel()
                     .Select(file =>
                     {
                         using MusicPlayer musicPlayer = new MusicPlayer(file, 0f);
                         using File musicFile = File.Create(file);

                         return new TrackModel()
                         {
                             FilePath = file,
                             Title = musicFile.Tag.Title,
                             Artist = musicFile.Tag.FirstPerformer,
                             Length = musicPlayer.GetLengthInSeconds(),
                         };
                     })
                     .ToList();
    return output;

}

使用AsParallel()大大缩短了加载时间,这正是我所要寻找的。由于这个聪明的想法,我将Enigmativity的答案标记为正确。最初,它抛出了一个奇怪的AggregateException,但是我能够通过将输出保存在一个变量中,然后返回它来解决它。

这也归功于marsze,它的建议帮助我修复了应用程序中的内存泄漏,并减少了16 me的内存(!)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73004174

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档