0

Below is a simple code demo of this problem, just execute StartQueueJob() and then ShowResult() after few seconds, here I list some test results after several tests:

1. Loop count: 1000, For count: 1000, Thread count: 999, Data.Count: 999 
2. Loop count: 1000, For count: 1000, Thread count: 990, Data.Count: 992
3. Loop count: 5000, For count: 5000, Thread count: 4534, Data.Count: 4527 
4. Loop count: 7, For count: 7, Thread count: 7, Data.Count: 7 
5. Loop count: 7, For count: 7, Thread count: 6, Data.Count: 6 

Tested on a 8 cores CPU Win7 64bit PC, .Net Framework 4.0 VS2010 pro. Functions were triggered by mouse click myself, I click a button to run StartQueueJob() and then click to run ShowResult() after few seconds.

I have 2 questions:

  1. Why sometimes Thread count != Data.Count?

  2. Why sometimes Thread count < For count?

List<int> Data = new List<int>();
int ForCount = 0;
int ThreadCount = 0;
private void StartQueueJob( )
{
    int iLoop = Convert.ToInt32(numericUpDown2.Value);
    Data = new List<int>(iLoop);
    ForCount = 0;
    ThreadCount = 0;

    for (int k = 0; k < iLoop; k++)
    {
        ForCount += 1;

        ThreadPool.QueueUserWorkItem(
        (obj) =>
        {
            ThreadCount++;
            Data.Add(ThreadCount);
        });
    }
}

private void ShowResult()
{
    Console.WriteLine(String.Format(
        "Loop count: {3}, For count: {0}, Thread count: {1}, Data.Count: {2} ",
        new object[] { ForCount, ThreadCount, Data.Count, numericUpDown2.Value }));
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
  • 4
    `ThreadCount++;` and `Data.Add` are not threadsafe and that's the answer I guess. Use a `lock` around them or use fork and join technique. – Sriram Sakthivel Sep 12 '14 at 07:23
  • 2
    List isn't either. Take some class like ConcurrentBag. – Pieter21 Sep 12 '14 at 07:26
  • You may also need waiting for the queue to finish: http://stackoverflow.com/questions/6529659/wait-for-queueuserworkitem-to-complete – Pieter21 Sep 12 '14 at 07:28
  • 2
    This is a great example of a few separate issues in multi-threading. Read up - http://www.albahari.com/threading/ Multi-threading is *hard*. – Luaan Sep 12 '14 at 08:01
  • Thanks to Sriram Sakthivel, I missed that ThreadCount is a public variable, and thanks to Pieter21, ConcurrentBag solved the problem. – user3093559 Sep 12 '14 at 08:56

1 Answers1

-2

Also this question is very old, I had a similar problem when writing a tcp-server - see this section:

// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);

// Start listening for client requests.
server.Start();

// Enter the listening loop.
while (true)
{
    TcpClient client = server.AcceptTcpClient();
    ThreadPool.QueueUserWorkItem(processMessage, client);
}

When receiving multiple messages at the same time, receive rate dropped down to 65%. Adding a piece of code before the QueueUserWorkItem, which uses a synchronized object, kept receive rate at 97% (in my case, this was a Log-entry). Another solution with the same result was simply using Threads instead of ThreadPool.

// Enter the listening loop.
while (true)
{
    TcpClient client = server.AcceptTcpClient();
    Thread t = new Thread(new ParameterizedThreadStart(processMessage));
    t.Start(client);
}

I reached 99% receive rate using a manual semaphore:

private static object syncObj = new Object();

...

// Enter the listening loop.
while (true)
{
    lock (syncObj)
    {
        TcpClient client = server.AcceptTcpClient();
        ThreadPool.QueueUserWorkItem(processMessage, client);
    }
}

I hope this helps!

Edit: I reached 100% now, the rest was caused by this: TcpClient.GetStream().DataAvailable returns false, but stream has more data

Giga
  • 77
  • 1
  • 4