Question

I have this function below and i want to understand this. Also if there any documentations you van point me to. I have read about ManualResetEvent and ThreadPool from msdn

public void GetParametersThreadPool()
{
    var toProcess = 50;
    ManualResetEvent[] threadsActive = new ManualResetEvent[50];
    for (int handleIndex = 0; handleIndex < 50; ++handleIndex)
    {
        threadsActive[handleIndex] = new ManualResetEvent(false);

        ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state)
            {
                string reportUrl = TeamFoundationTestConfig.TeamFoundationReportPath("TaskGroupStatus");
                ReportUri reportUri = ReportUri.Create(reportUrl);
                Log.Message(TraceEventType.Information, "ReportUri = {0}".InvariantFormat(reportUri.UriString));
                IList<Parameter> parameters = this.RemoteReportingServiceFactory.CreateReportParameterProvider().GetParameters(reportUri, SessionContext);
                Assert.IsNotNull(parameters, "Assertion failed: Parameters cannot be null. GetParameters failed");
                Assert.IsTrue(parameters.Count > 0, "Assertion failed: No parameters available on the report page. GetParameters failed. Count = {0}".InvariantFormat(parameters.Count));
                if (Interlocked.Decrement(ref toProcess) == 0)
                {
                    threadsActive[handleIndex].Set();
                }
            }), null);

        //// Wait for all the threads to complete before starting the next set of requests.
        threadsActive[handleIndex].WaitOne(); 
    }   
}

When i update this line of code : ManualResetEvent[] threadsActive = new ManualResetEvent[100];It gives en exception saying less than 64 only.

Currently when i run this stress tests it hangs on the line where i do Logging and doesn't finish running. What am i doing wrong?

If there is any better way to do this? Also just for information i referenced one other question from stackoverflow to create this function on my own

C# Execute Method (with Parameters) with ThreadPool

Was it helpful?

Solution

Depending on your .NET version you might want to use Task and Task.WaitAll(..), it comes with .NET 4. There's also CountdownEvent in your toolkit.

Using tasks is often as simple as

var t = Task.Factory.StartNew(() => { your code });
t.Wait();

If, for any reason, the Task Parallel Library is not an option, you might want to think about using Semaphores (SemaphoreSlim in .NET 4).

As for the 64 limit, this is an operating system enforced limit; Sadly there's no way around it.

OTHER TIPS

WaitOne Blocks the current thread until the current WaitHandle receives a signal, you are writing mulit-thread code but this method is sync method actually

create a variable that keeps track of the number of running tasks:

var toProcess = 50;

create one signal instead of array

   ManualResetEvent signal = new ManualResetEvent(false);

for (int handleIndex = 0; handleIndex < 50; ++handleIndex)
    {


        ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state)
            {
                string reportUrl = TeamFoundationTestConfig.TeamFoundationReportPath("TaskGroupStatus");
                ReportUri reportUri = ReportUri.Create(reportUrl);
                Log.Message(TraceEventType.Information, "ReportUri = {0}".InvariantFormat(reportUri.UriString));
                IList<Parameter> parameters = this.RemoteReportingServiceFactory.CreateReportParameterProvider().GetParameters(reportUri, SessionContext);
                Assert.IsNotNull(parameters, "Assertion failed: Parameters cannot be null. GetParameters failed");
                Assert.IsTrue(parameters.Count > 0, "Assertion failed: No parameters available on the report page. GetParameters failed. Count = {0}".InvariantFormat(parameters.Count));
                if (Interlocked.Decrement(ref toProcess) == 0)
                {
                    signal.Set();
                }
            }), null);


    }   

    signal.WaitOne();

don't put signal.WaitOne() in the for loop, that will block the thread.

finally, consider use Task if you are working on .net 3.5 or higher

As suggested, you should probably use Tasks if you can. Prior to their availability, it was possible to do what you want with just two WaitHandles. Instead of using one WaitHandle per thread, you use one WaitHandle for all threads. The waiting thread counts the number of times the WaitHandle is signalled and continues only when all signals have been received.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top