【问题标题】:Multithreaded using List多线程使用 List
【发布时间】:2014-01-22 08:07:10
【问题描述】:

可能是锁没有像我预期的那样工作。在这种情况下我应该使用静音吗?

以下代码发生错误。在 prod 上,它阻塞了我的电子邮件服务器。

错误邮件内容:

消息是:

索引超出了数组的范围。

堆栈跟踪是:

在 System.Collections.Generic.List`1.Add(T 项目)
在 TT.SharedServices.Auditor.Audit.AddAudit(AuditEventType pEvType,严重性 pSeverity,Int32 pClientId,字符串 pSessionId,字符串 pDetail,字符串 pClientIp,字符串 pEndUserIp)

内部例外是:

请求参数为:sessionID:df58b273-c399-4692-8c14-7400b219769e 详细信息:LoadAgency 的 TimeTaken:13 ms

 private void AddAudit(AuditEventType pEvType, Severity pSeverity, int pClientId, string pSessionId, string pDetail,
                    string pClientIp, string pEndUserIp)
 {
     // TO DO: also add Time
     Trace.TraceInformation("Audit.Add entered : ");
     try
     {
         if (pSeverity == Severity.High || Convert.ToBoolean(ConfigurationSystem.SharedApiConfig[pSeverity.ToString().ToLower()])) // chk option in config for adding audit
         {
             if (string.IsNullOrEmpty(pDetail))
             {
                 throw new ArgumentException("Detail should have a value", "pDetail");
             }
             // adding data
             var paramList = new DbParameter[8];
             paramList[0] = DataAccess.ParameterFactory.Create("@eventType", DbType.Int16, pEvType);
             paramList[1] = DataAccess.ParameterFactory.Create("@severity", DbType.Int16, pSeverity);
             paramList[2] = DataAccess.ParameterFactory.Create("@clientId", DbType.String, pClientId);
             paramList[3] = DataAccess.ParameterFactory.Create("@detail", DbType.String, pDetail);

             if (string.IsNullOrEmpty(pClientIp))
                 paramList[4] = DataAccess.ParameterFactory.Create("@clientIP", DbType.String, DBNull.Value);
             else
                 paramList[4] = DataAccess.ParameterFactory.Create("@clientIP", DbType.String, pClientIp);

             if (string.IsNullOrEmpty(pEndUserIp))
                 paramList[5] = DataAccess.ParameterFactory.Create("@endUserIP", DbType.String, DBNull.Value);
             else
                 paramList[5] = DataAccess.ParameterFactory.Create("@endUserIP", DbType.String, pEndUserIp);

             if (string.IsNullOrEmpty(pSessionId))
                 paramList[6] = DataAccess.ParameterFactory.Create("@sessionId", DbType.String,
                                                                   new Guid().ToString());
             else
                 paramList[6] = DataAccess.ParameterFactory.Create("@sessionId", DbType.String, pSessionId);

             paramList[7] = DataAccess.ParameterFactory.Create("@eventTime", DbType.DateTime, DateTime.Now);
             if (IsBulkAuditSharedApi)
             {
                 _auditQueueData.Add(paramList);
                 if (_auditQueueData.Count > MaxCountSharedApi)
                 {
                     AuditThreadData threadData = new AuditThreadData();
                     lock (_auditQueueData)
                     {
                         threadData.Audit = new List<DbParameter[]>();
                         threadData.Audit = _auditQueueData;
                         _auditQueueData = new List<DbParameter[]>();
                     }                           
                     Thread callAuditPush = new Thread(AuditPushThread);
                     callAuditPush.Start(threadData);
                 }
             }
             else
             {
                 int rowsAffected = DataAccess.ExecuteNonQuery(SpNames.IAPI_AddAudit, paramList);
                 Trace.TraceInformation("Audit.Add : Adding Audit data. rowsAffected = " + rowsAffected);
             }
             Trace.TraceInformation("Audit.Add exit : ");
         }
     }
     catch (Exception exception)
     {                
         string auditText = "The message is :" + exception.Message + "<br/> The Stack trace is :" + exception.StackTrace;
         auditText += "<br/> The Inner Exception is:" + exception.InnerException;
         auditText += "<br/> The Request parameters are : \n sessionID : " + pSessionId + "\n Details : " + pDetail;
         Email.Email.SendingErrorEmail("Exception in Adding Audit in IAPI :", auditText, true, Email.Email.EmailSeverity.Error);
     }
}


    struct AuditThreadData
    {
        internal List<DbParameter[]> Audit;
    }
    #region Private Static Methods
    /// <summary>
    /// This method will Audit the data(in Bulk) in DB
    /// </summary>
    /// <param name="objData"></param>
    private void AuditPushThread(object objData)
    {
        try
        {
            var data = (AuditThreadData)objData;
            if (data.Audit != null && data.Audit.Count > 0)
            {
                foreach (var paramList in data.Audit)
                {
                    if (DataAccess != null) DataAccess.ExecuteNonQuery(SpNames.IAPI_AddAudit, paramList);
                }
            }
        }
        catch (Exception ex)
        {
            // catch block for precaution. 
            try
            {
                var log = new EventLog {Source = "Application"};
                log.WriteEntry("Bulk audit add failed:" + ex.Message + ex.InnerException, EventLogEntryType.Error, 2344);                    
            }
            catch
            {
                // to handle system security crash while writing log
            }
        }
    }

【问题讨论】:

  • 您似乎没有对_auditQueueData 进行任何需要锁定的操作,但是您在_auditQueueData.Add(paramList); 的锁定之外。没有看到更多的代码上下文很难理解

标签: c# multithreading locking mutex


【解决方案1】:

您在锁外拨打_auditQueueData.Add(paramList);。试着把它放进去。

您还锁定到List 本身,而ICollections(如List)具有为此目的而存在的SyncRoot 属性。该属性可能被框架的其他部分(如 UI)使用。您需要将 List 显式转换为 ICollection 才能访问此属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多