开发者

Thread Executing the Same code block - passing parameters from a dataset c#

Let me preface my question by stating that I am a casual developer, so I don't really know what I am doing past the basics.

This is developed in c# and .net 3.5.

The core of what my current application is doing is to connect to remote servers, execute a WMI call, retri开发者_Python百科eve some data and then place this data into a database. It is a simple healthcheck application.

The basic code runs fine, but I ran into an issue where if a few servers were offline, it would take 1 minute to timeout (which is realistic because of network bandwidth etc). I had an execution of the application run for 45 minutes (because 40 servers were offline) which is not efficient, since the code executed for 45 minutes and 40 minutes wait time.

After some research I think that using threads would be the best way to get around it, if I spawned a thread for each of the servers as it was processing.

Here is my thread code:

for (int x = 0; x < mydataSet.Tables[0].Rows.Count; x++)
{
    Thread ts0 = new Thread(() => 
       executeSomeSteps(mydataSet.Tables[0].Rows[x]["IPAddress"].ToString(),
       mydataSet.Tables[0].Rows[x]["ID"].ToString(), connString, filepath));
    ts0.Start();                                            
}

The dataset contains an ID reference and an IP Address. The execute some steps function looks like this:

static void executeSomeSteps(string IPAddress, string ID, string connstring, string filepath)
{
      string executeStuff;
      executeStuff = funclib.ExecuteSteps(IPAddress, ID, connstring, filepath);
      executeStuff = null;
}

And execute some steps inserts data into a database based on returned wmi results. This process works fine as mentioned earlier but the problem is that some of the threads in the above for loop end up with the same data, and it executes more than once per server. There are often up to 5 records for a single server once the process completes.

From the research I have done, I believe it might be an issue with more than one thread reading the same x value from the dataset.

So now onto my questions:

Assume there are 10 records in the dataset:

Why are there more than 10 executions happening? Will I still gain the performance if I lock the dataset value? Can someone point me into the right direction regarding how to deal with variable data being passed to a static function by multiple threads?


What Davide refers to is that at the time you thread is executed the captured values from Rows[x] may be different (are even likely to be different) than when the delegate was created. This is because you the for loops goes on while the threads start running. This is a very common gotcha. It may even happen without servers timing out.

The solution to this "modified closure" problem is to use new variables for each thread:

for (int x = 0; x < mydataSet.Tables[0].Rows.Count; x++)
{
    string ip = mydataSet.Tables[0].Rows[x]["IPAddress"].ToString();
    string id = mydataSet.Tables[0].Rows[x]["ID"].ToString();
    Thread ts0 = new Thread(() => executeSomeSteps(ip, id, connString, filepath));
    ts0.Start();                                            
}

You may even encounter a System.ArgumentOutOfRangeException because when the for loop has finished, the last x++ may have executed, making x 1 higher than the row indexes. Any thread reaching its Rows[x] part will then throw the exception.


Edit

This issue kept bugging me. I think what you describe in your comment (it looked like extra records were being generated by one iteration) is exactly what the modified closure does. A few threads happen to start roughly at the same time, all taking the value of x at that moment. You must also have found that servers were skipped in one time lap, I cannot image that not happening.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜