并行.Foreach c#.net4.5.1的多线程处理

并行.Foreach c#.net4.5.1的多线程处理,c#,multithreading,linq,parallel-processing,.net-4.5,C#,Multithreading,Linq,Parallel Processing,.net 4.5,我有一个IEnumerable对象,它大约有10-15个条目,所以不是很多,但是当我尝试执行时,我遇到了一个System.IO.FileNotFoundException Parallel.Foreach(…一些linq查询…,对象=>{…stuff…}) 具有可枚举性。以下是我的代码,有时有效,有时无效: IEnumerable<UserIdentifier> userIds = script.Entries.Select(x => x.UserIdentif

我有一个
IEnumerable
对象,它大约有10-15个条目,所以不是很多,但是当我尝试执行时,我遇到了一个
System.IO.FileNotFoundException

Parallel.Foreach(…一些linq查询…,对象=>{…stuff…})

具有可枚举性。以下是我的代码,有时有效,有时无效:

        IEnumerable<UserIdentifier> userIds = script.Entries.Select(x => x.UserIdentifier).Distinct();

        await Task.Factory.StartNew(() =>
        {
            Parallel.ForEach(userIds, async userId =>
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();

                _Log.InfoFormat("user identifier: {0}", userId);
                await Task.Factory.StartNew(() =>
                {
                    foreach (ScriptEntry se in script.Entries.Where(x => x.UserIdentifier.Equals(userId)))
                    {
                        //    // Run the script //
                        _Log.InfoFormat("waiting {0}", se.Delay);
                        Task.Delay(se.Delay);
                        _Log.InfoFormat("running SelectionInformation{0}", se.SelectionInformation);

                        ExecuteSingleEntry(se);
                        _Log.InfoFormat("[====== SelectionInformation {1} ELAPSED TIME: {0} ======]", watch.Elapsed,
                            se.SelectionInformation.Verb);
                    }

                });

                watch.Stop();
                _Log.InfoFormat("[====== TOTAL ELAPSED TIME: {0} ======]", watch.Elapsed);
            });
        });
我引用了:获取


Task.Factory.StartNew(()=>Parallel.Foreach({}))
所以我的UI不会锁定在我身上

有几个原则可以应用:

  • 。我在我的博客上描述了为什么
    StartNew
    是危险的<代码>运行
  • 是一种更安全、更现代的选择
  • 不要将
    async
    lambda传递给
    Parallel.ForEach
    。这没有意义,也不会正常工作
  • Task.Delay
    本身没有任何作用。您要么等待它,要么使用同步版本(
    Thread.Sleep
  • (事实上,在您的例子中,内部的
    StartNew
    是没有意义的;它已经是并行的,并且在线程池线程上运行的代码正在尝试在线程池线程上启动一个新操作,并立即异步等待它??)

    在应用这些原则之后:

    await Task.Run(() =>
    {
      Parallel.ForEach(userIds, userId =>
      {
        Stopwatch watch = new Stopwatch();
        watch.Start();
    
        _Log.InfoFormat("user identifier: {0}", userId);
        foreach (ScriptEntry se in script.Entries.Where(x => x.UserIdentifier.Equals(userId)))
        {
          //    // Run the script //
          _Log.InfoFormat("waiting {0}", se.Delay);
          Thread.Sleep(se.Delay);
          _Log.InfoFormat("running SelectionInformation{0}", se.SelectionInformation);
    
          ExecuteSingleEntry(se);
          _Log.InfoFormat("[====== SelectionInformation {1} ELAPSED TIME: {0} ======]", watch.Elapsed,
              se.SelectionInformation.Verb);
        }
    
        watch.Stop();
        _Log.InfoFormat("[====== TOTAL ELAPSED TIME: {0} ======]", watch.Elapsed);
      });
    });
    

    你为什么不试试做
    ExecuteSingleEntry(se)线程安全如果您在
    Parallel.ForEach
    循环中所做的只是创建一些文件和目录,那么您也可以按顺序执行。速度可能会更高。大容量存储性能(而不是CPU)是您的瓶颈。根据
    ExecuteSingleEntry
    的实际功能,您可以尝试将文件创建和删除逻辑放在一个文件夹中
    ExecuteSingleEntry
    的功能远不止创建文件和目录。它进入oracle数据库并针对该数据库运行报告<创建code>.wsc
    文件并将其转储到目录中,以便对返回的数据进行分析。目前我正在尝试锁定文件创建。parallel.foreach用于在一个(半)大的数据集合上一次在每台运行分析的机器上复制3-5个用户,并且execute single entry函数根据选择信息选择分析路径。
    await Task.Run(() =>
    {
      Parallel.ForEach(userIds, userId =>
      {
        Stopwatch watch = new Stopwatch();
        watch.Start();
    
        _Log.InfoFormat("user identifier: {0}", userId);
        foreach (ScriptEntry se in script.Entries.Where(x => x.UserIdentifier.Equals(userId)))
        {
          //    // Run the script //
          _Log.InfoFormat("waiting {0}", se.Delay);
          Thread.Sleep(se.Delay);
          _Log.InfoFormat("running SelectionInformation{0}", se.SelectionInformation);
    
          ExecuteSingleEntry(se);
          _Log.InfoFormat("[====== SelectionInformation {1} ELAPSED TIME: {0} ======]", watch.Elapsed,
              se.SelectionInformation.Verb);
        }
    
        watch.Stop();
        _Log.InfoFormat("[====== TOTAL ELAPSED TIME: {0} ======]", watch.Elapsed);
      });
    });