0

I have a method that need to call webservice to get data. If each record(total 200) needs to be called once webservice,then it will take a long time(per more than 10 seconds one response). So I use asynchronous to improve efficiency. But I meet a problem. When using the Task, it should call 200 times Webservice, but it only calls more than 100 times lead to incomplete result.

Hope someone can help me, thank you very much.

Code:

string EffectiveDate = string.Empty;
IList<Task<string>> list = new List<Task<string>>();

foreach (DataRow dr in rows)
{
    var task = Task.Factory.StartNew(new Func<string>(() =>
    {
        string result = string.Empty;
        string columnId;
        try
        {
            var rates = GetMainRateModel(dr);
            lock (_objMainRatesAsync)
            {
                long seq = _redis.Core.IncrementValue(_currUserKey);
                columnId = dr["ColumnId"].GetString();
                EffectiveDate = Convert.ToDateTime(dr["Validity date"]).ToString("yyyy-MM-dd");
                if (rates != null)
                {
                    foreach (var rate in rates)
                    {
                        var surCharges = GetContractSurchargeModel(rate, EffectiveDate);
                        rate.Surcharges = surCharges;
                        GetVATOSSurcharges(rate, surCharges, EffectiveDate, dr);
                    }
                    _redis.Hash_Set(_currRates, columnId, rates);
                }
            }
        }
        catch (Exception eex)
        {
            lock (_objProcessRateAsync)
            {
                _sbErrors.AppendLine(string.Format("Error, when the get data from web service. Detail message: {0}", eex.Message));
            }
            result = eex.Message;
        }

        return result;
    }));

    list.Add(task);
}

Task.WaitAll(list.ToArray());
tyler_mitchell
  • 1,727
  • 1
  • 19
  • 27
Edwin Nie
  • 3
  • 3
  • Your code seems to have multiple threading issues. The main problem is the use of the captured `dr` but I'm not sure if that's the only one. – H H Aug 03 '17 at 10:08
  • just some tips: if the `GetContractSurchargeModel()/GetVATOSSurcharges()` doesn't use any state. try to get the `foreach (var rate in rates)` out of the loop. Also if the `GetContractSurchargeModel()` does a lookup in the database. You should use a db connection each task. You might pass the dbconnection object as parameter. – Jeroen van Langen Aug 03 '17 at 10:11
  • 1
    If you're not awaiting the results but block until they are done. You should switch to `Parallel.Foreach(....)` which also solves the _"captured dr"_ – Jeroen van Langen Aug 03 '17 at 10:13

1 Answers1

0

Like the other said. You have a problem in the method which is running on several threads.

A good habit is to run ONLY static methods on threads. It stops you from using "shared variables" unintentionally between several threads. A good practice is to declare all parameters, which method running on several threads needs - and pass them in "Task.Factory.StartNew" method

One more good tip. Use Task.Run instead of Task.Factory.StartNew

here is why: Regarding usage of Task.Start() , Task.Run() and Task.Factory.StartNew())

Piotr
  • 1,155
  • 12
  • 29