Question

I'm working on a Windows Service that cycles through a series of databases and then sends SMS messages using HTTP requests. In the beginning of the method that goes through each database, I define a generic list as follows:

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

I populate that list with the results of an asynchronous HTTP request sent through a thread pool:

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

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

    ThreadPool.QueueUserWorkItem(SendSMS, oSMS);
}

Then it gets passed to the next method:

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

Then to GetRequestStreamCallback...

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

And finally the response is received and added to the Recipients List:

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);
    }

At the end of the code, each response should be added to a Recipient object and then stored in the generic list. The problem is that once about every 1000 or so SMS messages (sent in batches of 50), there is an unhandled IndexOutOfRangeException thrown by the line of code Recipients.Add(CompleteMessage).

I didn't think that there were indexes in the list, and many of the recipients are duplicates. Why would it throw this error, and why only every once in a good while? Could this have to do with threading issues?

As a note, I'm activating the main method from a Timer object, but it will wait until the previous instance is complete before starting a new instance.

Edit: Here is the Recipient class:

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; }
}
Was it helpful?

Solution

My guess would that you're running into multiple threads trying to add to Recipients at the same time and one beginning before the prior has finished.

Try locking your Recipients during read and writes and see if it helps:

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;
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top