-2

I have a programming that is looping x times (10), and using a specified number of threads (2). I'm using a thread array:

Thread[] myThreadArray = new Thread[2];

My loop counter, I believe, starts the first 2 threads just fine, but when it gets to loop 3, which goes back to thread 0 (zero-based), it hangs. The weird thing is, if I throw a MessageBox.Show() in their to check the ThreadState (which shows thread 0 is still running), it will continue on through 9 of the 10 loops. But if no MessageBox.Show() is there, it hangs when starting the 3rd loop.

I'm using .NET 3.5 Framework (I noticed that .NET 4.0 utilizes something called continuations...)

Here's some code examples:

        Thread[] threads = new Thread[2];
        int threadCounter = 0;

        for (int counter = 0; counter < 10; counter++)
        {
            if (chkUseThreading.Checked)
            {
                TestRunResult runResult = new TestRunResult(counter + 1);
                TestInfo tInfo = new TestInfo(conn, comm, runResult);

                if (threads[threadCounter] != null)
                {
                    // If this is here, then it will continue looping....otherwise, it hangs on the 3rd loop
                    MessageBox.Show(threads[threadCounter].ThreadState.ToString());

                    while (threads[threadCounter].IsAlive || threads[threadCounter].ThreadState == ThreadState.Running)
                        Thread.Sleep(1);

                    threads[threadCounter] = null;
                }

                // ExecuteTest is a non-static method
                threads[threadCounter] = new Thread(new ThreadStart(delegate { ExecuteTest(tInfo); }));
                threads[threadCounter].Name = "PerformanceTest" + (counter + 1);

                try
                {
                    threads[threadCounter].Start();

                    if ((threadCounter + 1) == threadCount)
                        threadCounter = 0;
                    else
                        threadCounter++;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }

                Application.DoEvents();
            }
        }

            while (true)
            {
                int threadsFinished = 0;

                for (int counter = 0; counter < threadCount; counter++)
                {
                    if (!threads[counter].IsAlive || threads[counter].ThreadState == ThreadState.Stopped)
                        threadsFinished++;
                }

                if (threadsFinished == threadCount)
                    break;
                else
                    Thread.Sleep(1);
            }

Obviously the problem is something about how I'm checking to see if thread #1 or #2 is done. The IsAlive always says true, and the ThreadState always has "running" for threads loops 1 and 10.

Where am I going wrong with this?

Update, here's the ExecuteTask() method:

        private void ExecuteTest(object tInfo)
    {
        TestInfo testInfo = tInfo as TestInfo;

        Exception error = null;
        DateTime endTime;
        TimeSpan duration;
        DateTime startTime = DateTime.Now;

        try
        {
            if (testInfo.Connection.State != ConnectionState.Open)
            {
                testInfo.Connection.ConnectionString = connString;
                testInfo.Connection.Open();
            }

            testInfo.Command.ExecuteScalar();
        }
        catch (Exception ex)
        {
            error = ex;
            failedCounter++;

            //if (chkCancelOnError.Checked)
            //    break;
        }
        finally
        {
            endTime = DateTime.Now;
            duration = endTime - startTime;
            RunTimes.Add(duration);

            testInfo.Result.StartTime = startTime;
            testInfo.Result.EndTime = endTime;
            testInfo.Result.Duration = duration;
            testInfo.Result.Error = error;
            TestResults.Add(testInfo.Result);

            // This part must be threadsafe...
            if (lvResults.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(ExecuteTest);
                this.Invoke(d, new object[] { tInfo });
            }
            else
            {
                lvResults.Items.Add(testInfo.Result.ConvertToListViewItem());

                #region Update Results - This wouldn't work in it's own method in the threaded version
                const string msPrefix = "ms";

                // ShortestRun
                TimeSpan shortest = GetShortestRun(RunTimes);
                tbShortestRun.Text = shortest.TotalMilliseconds + msPrefix;

                // AverageRun
                TimeSpan average = GetAverageRun(RunTimes);
                tbAverageRun.Text = average.TotalMilliseconds + msPrefix;

                // MeanRun
                TimeSpan mean = GetMeanRun(RunTimes);
                tbMeanRun.Text = mean.TotalMilliseconds + msPrefix;

                // LongestRun
                TimeSpan longest = GetLongestRun(RunTimes);
                tbLongestRun.Text = longest.TotalMilliseconds + msPrefix;

                // ErrorCount
                int errorCount = GetErrorCount(TestResults);
                tbErrorCount.Text = errorCount.ToString();
                #endregion
            }

            testInfo.Command.Dispose();

            Application.DoEvents();
        }
    }
Tyler Hyndman
  • 1,402
  • 3
  • 17
  • 24
ganders
  • 7,285
  • 17
  • 66
  • 114
  • What do you really want to do? It is really hard to read your question – L.B Dec 16 '11 at 23:04
  • When it gets to the 3rd loop, the ThreadState never changes away from "running", or the IsAlive property never moves away from "true" so it will never start processing the 3rd loop. And my while loop that is their to check for those values doesn't seem to be any help, the program just sits there and I have to kill the app. – ganders Dec 16 '11 at 23:08
  • I ask what it your intention? Something like `I want to run ExecuteTest 10 times by two threads` etc. – L.B Dec 16 '11 at 23:11
  • Sorry, yes, that's exactly what I want to do....run the loop 10 times using 2 separarte threads to make it get done faster and put a larger load on my SQL Server at the same time. – ganders Dec 16 '11 at 23:21
  • 3
    Ouch. You're calling `Application.DoEvents()` on another Thread? It's evil enough on the main Thread. – H H Dec 16 '11 at 23:23
  • Henk, how else do I "repaint" my form to see results while it's still processing? – ganders Dec 16 '11 at 23:29
  • ganders, The main part that launches the Threads should not be blocking/sleeping. Maybe move it to a Backgroundworker. – H H Dec 17 '11 at 00:02
  • Henk, I don't believe it is, the only thing that the main thread does is start the 2 "other" threads that call the "ExecuteTest" method. Inside the "ExecuteTest" method is part that does the "InvokeRequired" for updating the listview. Or are you saying the Application.DoEvents() is the part that is blocking via the main thread even though it's called from one of the other threads? – ganders Dec 19 '11 at 16:15
  • Oh, by the way, I changed the Application.DoEvents() to use Refresh() instead, is that a better option? – ganders Dec 19 '11 at 16:23
  • Thanks Henk. I changed everything to use that SynchronizationContext class to do all the updates to the UI controls and now everything works great. – ganders Dec 20 '11 at 19:12
  • @HenkHolterman you want to post your answer about the SynchronizationContext so I can give you credit...? – ganders Jun 15 '12 at 12:57

1 Answers1

0

Can you post a snippet of run ()? Doesn't Thread.currentThread().notifyAll() help? May be each thread is waiting for other thread to do something resulting in a deadlock?

  • I'm assuming you are talking about the "ExecuteTask()" when you say "Run()"...I added it to the original post. – ganders Dec 16 '11 at 23:02
  • I'll need to lookup Thread.CurrentThread().NotifyAll() because I've never seen/heard of that. – ganders Dec 16 '11 at 23:11
  • He is referring to the wait/notify mechanism/pattern, but is mixing up Java and .NET. On the Java Platform, the Object class (not the Thread class, mind you) provides wait(), notify() and notifyAll(). This set of methods can be used to implement inter-thread signalling. The corresponding set of methods in the .NET Framework can be found in System.Threading.Monitor (Wait, Pulse, and PulseAll). – afrischke Dec 17 '11 at 02:07