2012-12-20 106 views
1

我正在使用循環訪問一系列數據庫,然後使用HTTP請求發送SMS消息的Windows服務。在通過每個數據庫雲的方法的開頭,我定義了一個通用的清單如下:異步HTTP請求在通用列表中拋出IndexOutOfRange異常

public static List<Recipient> Recipients = new List<Recipient>(); 

我填充一個異步HTTP請求通過一個線程池發送的結果列表:

//inside main method      
foreach (var SMS in SMSJoin) 
{ 
    ... 

    SMSMessage oSMS = new SMSMessage(Keyword, Number, Message, MessageID); 

    ThreadPool.QueueUserWorkItem(SendSMS, oSMS); 
} 

然後,它被傳遞到下一個方法:

public static void SendSMS(object SMStoSend) 
{ 
    try 
    { 
     SMSMessage oSMS = (SMSMessage)SMStoSend; 
     ... 
     Request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), state); 
    } 
    ... 
} 

然後GetRequestStreamCallback ...

public static void GetRequestStreamCallback(IAsyncResult AsynchronousResult) 
{ 
    State state = (State)AsynchronousResult.AsyncState; 
    SMSMessage oSMS = state.oSMS; 
    try 
    { 
     ... 
     Request.BeginGetResponse(new AsyncCallback(ReceiveResponse), state); 
    } 
    ... 
} 

最後的響應被接收,並添加到收件人列表:

public static void ReceiveResponse(IAsyncResult Result) 
{ 
    ... 
    finally 
    { 
     oSMS.Complete = DateTime.Now; 

     Recipient CompleteMessage = new Recipient(oSMS.MessageID, oSMS.Recipient, oSMS.ErrorCode, oSMS.Complete, oSMS.ResponseCode); 
     Recipients.Add(CompleteMessage); 
    } 

在代碼的結束時,每個響應應該被添加到一個Recipient對象,然後被存儲在通用列表。問題是,大約每1000條左右的SMS消息(分批發送50條)一次,代碼行Recipients.Add(CompleteMessage)引發了未處理的IndexOutOfRangeException

我不認爲列表中有索引,許多收件人都是重複的。爲什麼會拋出這個錯誤,爲什麼只有每一次都在一段好時間?這可能與線程問題有關嗎?

作爲說明,我將從Timer對象中激活主要方法,但它將等待直到先前的實例完成,然後再啓動新的實例。

編輯: 這裏是Recipient類:

public class Recipient 
{ 
    public Recipient(long MessageID, string PhoneNumber, string ErrorMessage, DateTime? Completed, string Response) 
    { 
     this.MessageID = MessageID; 
     this.PhoneNumber = PhoneNumber; 
     this.ErrorMessage = ErrorMessage; 
     this.Completed = Completed; 
     this.Response = Response; 
    } 

    public long MessageID { get; set; } 
    public string PhoneNumber { get; set; } 
    public string ErrorMessage { get; set; } 
    public DateTime? Completed { get; set; } 
    public string Response { get; set; } 
} 
+0

這聽起來像它可能是一個線程問題。你有沒有嘗試讓'Recipients'成爲一套帶鎖的支持屬性? – Khan

+1

@JefferyKhan聽起來像是什麼,但是當執行'.Add()'時鎖定'Recipients'。它只設置一次。 – CodeCaster

回答

2

我的猜測是,你正在運行到多個線程試圖在同一時間添加到收件人和一個初已經完成了前前。

嘗試讀取過程中鎖定您的收件人和寫入,並看看是否有幫助:

private static object mylock = new object(); 
private static List<Recipient> _recipients = new List<Recipient>(); 
public static List<Recipient> Recipients 
{ 
    get 
    { 
     List<Recipient> result; 
     lock (mylock) 
     { 
      result = _recipients; 
     } 
     return result; 
    } 
    set 
    { 
     lock (mylock) 
     { 
      _recipients = value; 
     } 
    } 
} 
+0

我不熟悉鎖的使用。我應該把這個鎖分配給某個東西,還是在你列出的時候使用它? – ijb109

+0

按照我上面提到的使用它,看看你是否仍然遇到異常。請注意,有兩種不同的方式來實現它。我最初的想法,CodeCaster的。不要這樣做;) – Khan

+0

那麼,迄今爲止這麼好,但這將是一個困難的測試:) – ijb109