user1550951
user1550951

Reputation: 379

Set Timeout on Parallel.Foreach loop

I have to send a List of my custom object("Dial") to the client from my WCF service.This object has 5 properties:Id,Name,Type,Individual_avg,Dept_avg. The values for Id,Name and Type are coming from a table but the Individual_avg and dept_avg are coming from a 3rd party service.The requirement is:

  1. Load the static properties - Id,Name,Type from a table
  2. Call a method within the WCF service that gets the other 2 property values from the 3rd party service.

I have to timeout the call to 3rd party service after 30 seconds.That is,if the service takes more than 30 seconds to respond,I have to send the objects with only the 3 properties fetched from the table(Id,Name,Type) and set the other 2 properties to null. For example,there are 5 Dials in the List. Spawn 5 threads to call the 3rd party service to get the 2 properties.If the timeout occurs after getting the values for 2 Dials,send the List with all properties set for these 2 Dials and only Id,Name and Type set for the other 3 Dials. I have the following code to achieve it.

public DialResponse GetDials(DialRequest req)
{
    DialResponse response = new DialResponse();
    var indiDials = new List<DialDetails>();
    foreach (var c in indiDialIdToShow)
    {
        var indiObj = _repository.FindQueryable<DashboardDial_Tbl>().Where(p => p.DialId == c.DialIdToShow && p.IsActive == true).Select(p => new DialDetails()
            {
                Id = p.DialId,
                Name = p.DialName,
                Type = p.DialType,
             }).SingleOrDefault();
        indiDials.Add(indiObj);
    }
var timeout = 30000; // 30 seconds
var cts = new CancellationTokenSource();
var token = new CancellationToken();
token = cts.Token;
var myOptions = new ParallelOptions { CancellationToken = cts.Token };
using (var t = new Timer(_ => cts.Cancel(), null, timeout, -1))
{
    Parallel.ForEach(indiDials, myOptions, c =>
    {
        DialDetails newDial = c;
        ReadConfig(c.Id, userName, ref newDial);
        //send a reference to the "dial" object and set the 2 properties on the object

     });
 }
response.DialsList = indiDials;
}

private void ReadConfig(string userName,ref DialDetails dialObj)
{
   //call the 3rd party service
   dialObj.Individual_avg = serviceResponse.someValue;
   dialObj.dept_avg = serviceResponse.anotherValue;
}

To test the "timeout" functionality,I put a Thread.Sleep(40000) in "ReadConfig" method.This returns an empty list of "Dials" instead of the sending "Dials" with only 3 properties(Id,Name,Type) set. What changes should I make so that this piece of code works as intended?

Upvotes: 1

Views: 2533

Answers (1)

user2480047
user2480047

Reputation:

ReadConfig is performing the modifications locally and thus indiDials is not updated. You can convert it into a function to return the modified item. Sample code:

private DialDetails ReadConfig(string userName,ref DialDetails dialObj)
{
   //call the 3rd party service
   dialObj.Individual_avg = serviceResponse.someValue;
   dialObj.dept_avg = serviceResponse.anotherValue;

   retun dialObj;
}

And call it from the loop such that the List is modified:

indiDials[indiDials.IndexOf(newDial)] = ReadConfig(userName, ref newDial);

Upvotes: 1

Related Questions