Sriram B
Sriram B

Reputation: 691

Multithreaded foreach

I have list of ReferenceIDs (string) in a dataset. These ReferenceIDs can have values like this ("CQ1258891","CQ1258892","CQ1258893"....""CQ1258993"). I have a logic in my code to send a mail for each ReferenceIDs.

As of now I am looping through the every ReferenceID synchronously. Due to which, it take more time to send every mail. I have been using .NET 3.0, so I dont have option to use TPL in .NET 4.0.

I have been looking for a multithreaded machanism to send the mails for every ReferenceID asynchronously. As of now, I have tried the following code but it's not working as expected.

foreach (DataRow row in qrefSet.Tables[0].Rows)
{
    string refId = Convert.ToString(row["ReferenceID"]);
    if (!string.IsNullOrEmpty(refId))
    {
        Thread thread = new Thread(() => apeDBAdapter.SendEmail(personId, refId, parentReferenceID, customerName, queueId));                                    
        thread.Start();
    }
}

Please share the effective machanism to achieve multithreaded foreach loop for my implementation.

Thanks, Sriram

Upvotes: 0

Views: 1846

Answers (3)

cincura.net
cincura.net

Reputation: 4150

You can use this structure to do it. It uses ThreadPool so it's not creating a lot of threads, though better idea will be to use APM to send emails, hence no threads will be wasted.

It waits for all background operations are done. The data is your dataset's rows.

int opsLeft = data.Count();
using (var mre = new ManualResetEvent(false))
{
    foreach (DataRow row in data)
    {
        string refId = Convert.ToString(row["ReferenceID"]);
        if (!string.IsNullOrEmpty(refId))
        {
            ThreadPool.QueueUserWorkItem(_ =>
            {
                apeDBAdapter.SendEmail(personId, refId, parentReferenceID, customerName, queueId);
                if (Interlocked.Decrement(ref opsLeft) == 0)
                    mre.Set();
            });
        }
        else
        {
            if (Interlocked.Decrement(ref opsLeft) == 0)
                mre.Set();
        }
    }
    mre.WaitOne();
}

Upvotes: 0

Yair Nevet
Yair Nevet

Reputation: 13003

You can create a method that takes a range of items from the rows collection and run it multi-threaded according to the number of devision.

For example:

SendEmailsToReferencesByRange(int start, int end, DataRowCollection rows)
{
  foreach(var item in rows.Range(start, end-start))
  {
     //Do your sending logic here
  }
}

Usage:

//if for example you have 200 items than you can run it in 2 threads
Thread thread = new Thread(()=>SendEmailsToReferencesByRange(0,100, table[0].Rows)).Start();
Thread thread = new Thread(()=>SendEmailsToReferencesByRange(100,200, table[0].Rows)).Start();

Upvotes: 0

Virus
Virus

Reputation: 2541

Try this

foreach (DataRow row in qrefSet.Tables[0].Rows)
{
    string refId = Convert.ToString(row["ReferenceID"]);
    if (!string.IsNullOrEmpty(refId))
    {
        Thread thread = new Thread(new ParameterizedThreadStart(SendMail));
        thread.Start(refId)           
    }
}
..........
void SendMail(object refId)
{
    string strRefId = (string)refId;
    apeDBAdapter.SendEmail(personId, refId, parentReferenceID, customerName, queueId));  
}

hope it helps...

Upvotes: 2

Related Questions