首页 > 解决方案 > 如何保持不同的线程有自己的变量计算?

问题描述

因此,如果我尝试在序列化中执行此代码,则需要很长时间。所以我想用线程来做。但我遇到了安全问题。这是启动线程的内容:

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! ");  
    }
}

这是一个地方,我相信我遇到了一些不安全的情况,我真的不知道是否有解决问题的方法。我无法锁定(...)所有代码。因为那会破坏目的。所以很多计算发生在一个子类中。我相信问题是当这个子类被调用时,在多个线程中......我得到的答案通常是相同的答案。

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);

标签: c#asp.netmultithreadingvisual-studiothread-safety

解决方案


这就是状态对象的用途,您可以将一个对象传递给线程,让它单独修改该对象,然后在线程结束时对另一个方法执行某种回调,或者您可以使用该Join方法等待要完成的工作。

与其将 null 传递给QueueUserWorkItem,不如传递一个类的实例,其中包含线程完成工作和报告结果所需的一切。

说了这么多,如果你切换到使用Task一切可能会简单得多,但不确定你使用的是什么版本的 .NET / .NET 核心......


推荐阅读