简体   繁体   English

为什么计数器在线程池中不起作用

[英]Why the counter does not work in threadpool

I made a simple application using the threadpool, but when I do the counter inside or outside the threadpool, it just returns zero in all cases or Non - sequential numbers?我使用线程池做了一个简单的应用程序,但是当我在线程池内部或外部执行计数器时,它在所有情况下都返回零还是非序列号?

My program [ I am sending 10 thousand valuable webrequest [API] and I knew that threadpool faster way?我的程序 [我正在发送 10,000 个有价值的 webrequest [API] 并且我知道线程池更快的方法? Because I want to send and receive 10,000 request within 5 to 10 minutes.因为我想在 5 到 10 分钟内发送和接收 10,000 个请求。 ] ]

    public int Count;

    private void TaskCallBack(Object ThreadNumber)
    {
        MessageBox.Show(Count.ToString());  

        Interlocked.Increment(ref Count);
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        try
        {
            //// Queue the task.
            for (int x = 0; x < 10; x++)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(TaskCallBack));
            }

            this.Count = 0;
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error : " + ex);
        }
    }

Well, you can have 10 threads all print out the initial value of Count before any one of them increments the value.好吧,您可以让 10 个线程在其中任何一个增加值之前都打印出Count的初始值。 There's no guarantee of consecutive order, either, should threads increment Count prior to other threads calling Show .如果线程在其他线程调用Show之前增加Count ,也不能保证连续顺序。 To get both, use a mutex to control concurrent access to your callback's logic:要获得两者,请使用互斥锁来控制对回调逻辑的并发访问:

    public int Count;
    private readonly object _countLock = new Object();

    private void TaskCallBack(Object ThreadNumber)
    {
        lock( _countLock )
        {
            ++Count;
            MessageBox.Show(Count.ToString());
        }
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        try
        {
            // this smells
            this.Count = 0;

            //// Queue the task.
            for (int x = 0; x < 10; x++)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(TaskCallBack));
            }

        }
        catch (Exception ex)
        {
            MessageBox.Show("Error : " + ex);
        }
    }

When you use the Interlocked class to manipulate a variable, then all access to this variable must be done through the Interlocked class.当您使用Interlocked类操作变量时,必须通过Interlocked类完成对该变量的所有访问。 Otherwise there is no guarantee that you'll get the current value of the variable.否则无法保证您将获得变量的当前值。 So, for starters, the Count variable should not be made public .因此,对于初学者来说, Count变量不应public

private int _count;

public int Count => Interlocked.CompareExchange(ref _count, 0, 0);

private void TaskCallBack(Object ThreadNumber)
{
    var localCount = Interlocked.Increment(ref _count);
    MessageBox.Show(localCount.ToString());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM