簡體   English   中英

遞歸方法中的Parallel.ForEach

[英]Parallel.ForEach in recursive method

我有一種收集共享信息並將結果寫入數據庫的方法,我使用Parallel.Foreach可以提高性能,尤其是在掃描100 TB時

如果我在本地數據庫中運行此代碼,則沒有問題,但是在沙盒數據庫中,我遇到了大量異常/ innerExceptions

碼:

private static INodeCollection NodesLookUp(string path, int maximumLevel)
       {

           var shareCollectionNode = new ShareCollection(path);
           shareCollectionNode.GetNodeProperties();
           shareCollectionNode.GetPermissionEntires();
           WriteNodeToDatabase(shareCollectionNode); // write collected infomation to database
           if (maximumLevel <= 0 && _maximumSubLevels != -1)
           {
               return shareCollectionNode;
           }

           Parallel.ForEach(Directory.GetDirectories(shareCollectionNode.FullPath), directory =>
           {
              try
             {
                  lock (shareCollectionNode)
                  {
                      shareCollectionNode.AddNode(NodesLookUp(directory, maximumLevel - 1));
                  }

              }
              catch (UnauthorizedAccessException unauthorizedAccessException)
              {
                  lock (_shareIssues)
                  {
                      _shareIssues.Add(new ShareIssue(TraceStatu.UnauthorizedAccess, directory,
                     unauthorizedAccessException.Message, dfsId, currentLevel));
                  }

               }

           });

           return shareCollectionNode;
       }

寫入數據庫:

private static void WriteNodeToDatabase(ShareCollection shareCollection)
    {
        var nodeId = Persistence.UpsertShare(shareCollection);
        var sharePermissions = new List<IPermissionRight>();
        foreach (var permissionEntry in shareCollection.PermissionEntries)
        {
            permissionEntry.NodeId = nodeId;
            var permissionEntryId = Persistence.InsertPermissionEntry(permissionEntry);
            permissionEntry.SetPermissions(permissionEntryId);
            sharePermissions.AddRange(permissionEntry.Permissions);
        }
        Persistence.InsertPermissions(sharePermissions);
    }

例外情況:

    System.Data.SqlClient.SqlException (0x80131904): Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()

如果我刪除Parallel.Foreach並使用正常的for循環,那么除了應用程序需要花一些時間才能運行之外,我沒有任何問題。

首先嘗試替換這個

lock (shareCollectionNode)
{
    shareCollectionNode.AddNode(NodesLookUp(directory, maximumLevel - 1));
}

有了這個

var node = NodesLookUp(directory, maximumLevel - 1);
lock (shareCollectionNode)
{
    shareCollectionNode.AddNode(node);
}

和第二把鎖一樣。

盡管這是通過並行實現所需目標的更好方法,但它也可能有助於在本地重現相同的錯誤,因為這會增加數據庫活動。

我認為實際的問題取決於數據庫事務-看起來在並發數據庫操作期間導致表中的中間結果返回無效數據; 在我們看到實際的查詢和表架構之前,我無法說更多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM