使用List进行多线程处理

时间:2014-01-22 08:07:11

标签: c# multithreading locking mutex

可能锁定无法正常工作。在这种情况下我应该使用静音吗?

以下代码出错。它刺激了我的电子邮件服务器。

错误邮件内容:

消息是:

  

索引超出了数组的范围。

堆栈跟踪是:

  

at System.Collections.Generic.List`1.Add(T item)
  在TT.SharedServices.Auditor.Audit.AddAudit(AuditEventType pEvType,Severity pSeverity,Int32 pClientId,String pSessionId,String pDetail,String pClientIp,String pEndUserIp)

内部异常是:

  

请求参数是:sessionID:df58b273-c399-4692-8c14-7400b219769e详细信息:TimeAaken for LoadAgency: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
            }
        }
    }

1 个答案:

答案 0 :(得分:0)

你在锁外呼叫_auditQueueData.Add(paramList);。试着把它放进去。

此外,您锁定List本身,而ICollections(如列表)具有SyncRoot属性,为此目的而存在。此属性可能由框架的其他部分(如UI)使用。您需要明确地将List投射到ICollection才能访问此媒体资源。