Robert Koernke
Robert Koernke

Reputation: 435

How do I keep different threads to have their own variable calculations?

So it takes too long, if I try to do this code in serialization. So I want to do it with threading. But I'm running into safety-problems. Here is what starts the threads:

protected void Page_LoadComplete(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        using (var finished = new CountdownEvent(1))
        {
            for (int i = 1; i <= Convert.ToInt32(ViewState["Count"]); i++)
            {
                string k = i.ToString();
                ThreadInfo threadInfo = new ThreadInfo();
                threadInfo.f = k;
                finished.AddCount(); // Indicate that there is another work item.
                ThreadPool.QueueUserWorkItem(
                   (state) =>
                   {
                       try
                       {
                           Debug.WriteLine("Thread-Start Part " + k.ToString());
                           CalcThread(threadInfo);
                       }
                       finally
                       {
                           finished.Signal(); // Signal that the work item is complete.
                       }
                   }, null);
                Thread.Sleep(300);
            }
            Debug.WriteLine("Waiting till threads are done! ");
            finished.Signal(); // Signal that queueing is complete.
            finished.Wait(); // Wait for all work items to complete.
            Debug.WriteLine("Threads have completed! ");  
    }
}

Here is one place that I believe I'm getting some unsafe conditions, and I really don't know if there is a way to solve the problems. I cannot Lock ( ... ) all the code. Because that would defeat the purpose. So a lot of the calculations happen in a sub-class. The problem, I believe is when this sub-class is called, in multiple threads... the answers I'm getting back are often the same answers.

m_calculation.StartQuotePart(runnerweight, waste, machinesize, injectioncycle, volumefactor, MOQ);

m_calculation.partCostNoShiping = m_calculation.partCostNoShiping / partquantity * (1.0 + partcommission);
m_calculation.FedExShippingCost = m_calculation.FedExShippingCost / partquantity * (1.0 + partcommission);
m_calculation.DHLShippingCost = m_calculation.DHLShippingCost / partquantity * (1.0 + partcommission);
m_calculation.UPSShippingCost = m_calculation.UPSShippingCost / partquantity * (1.0 + partcommission);
m_calculation.OceanShippingCost = m_calculation.OceanShippingCost / partquantity * (1.0 + partcommission);

m_calculation.materialcost_out = m_calculation.materialcost_out / partquantity;
m_calculation.ProcessCost_out = m_calculation.ProcessCost_out / partquantity;
m_calculation.DHLshippingcost_out = m_calculation.DHLshippingcost_out / partquantity;

I have an instance for m_calculation... in the same class that is kicking off the threads. Is there a better way to access it, that wouldn't cause the issues. Is there a better way to create the threads that would cause the variable-mis-mash? This is supposed to run during the 'Page-Load-Complete' and then wait for the threads to complete with 'Finish-Wait'

Edit: I'm updating the Load-Complete with this based on jjxtra's post...

        int count = Convert.ToInt32(ViewState["Count"]);
        var tasks = new Task[count];
        for (int i = 1; i <= count; i++)
        {
            string k = i.ToString();
            ThreadInfo threadInfo = new ThreadInfo();
            threadInfo.f = k;
            tasks[i - 1] = Task.Factory.StartNew(() =>
            {
                CalcThread(threadInfo);
            });
        }
        Task.WaitAll(tasks);

Upvotes: 0

Views: 80

Answers (1)

jjxtra
jjxtra

Reputation: 21140

That's what the state object is for, you can pass an object to the thread, let it modify that object in isolation and then execute some sort of callback at the end of the thread to another method, or you can use the Join method to wait for the work to complete.

Instead of pasing null to QueueUserWorkItem, pass an instance of a class with everything the thread needs to do it's work and report results.

Having said all this, if you switch to using Task everything might be much simpler, but not sure what version of .NET / .NET core you are using...

Upvotes: 2

Related Questions