1

一連のデータベースを循環し、HTTP 要求を使用して SMS メッセージを送信する Windows サービスに取り組んでいます。各データベースを通過するメソッドの最初に、次のように一般的なリストを定義します。

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 件のバッチで送信される) ごとに 1 回IndexOutOfRangeException、コード行によってunhandled throw が発生することですRecipients.Add(CompleteMessage)

リストにインデックスがあるとは思いませんでした。受信者の多くは重複しています。なぜこのエラーがスローされるのでしょうか。これはスレッド化の問題と関係がありますか?

注意として、オブジェクトからメイン メソッドをアクティブにし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; }
}
4

1 に答える 1

2

私の推測では、複数のスレッドが同時に受信者に追加しようとしていて、前のスレッドが完了する前に 1 つのスレッドが開始されていると思います。

読み取りおよび書き込み中に受信者をロックしてみて、それが役立つかどうかを確認してください。

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;
        }
    }
}
于 2012-12-20T21:44:35.973 に答える