DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 7 of 7

Thread: C# and ThreadPools

  1. #1
    Erik Funkenbusch Guest

    C# and ThreadPools


    Ok, i've been trying to wrap my head around ThreadPools being used with C#,
    and it just keeps getting lost somewhere. Specifically I want to use ThreadPools
    to service Socket connections.

    From what I read, I can bind a socket handle to a ThreadPool, but it makes
    no sense as to how to make this call the correct callback when data comes
    in.

    Most of the samples i've found for ThreadPools only use QueueUserWorkItem.
    Some of the use RegisterWaitForSingleObject. Now, it seems like I could
    use RegisterWaitForSingleObject, but you have to create the socket as overlapped,
    however, TcpListen does the creation of the socket for you and doesn't appear
    to have an option to create the socket overlapped (though oddly enough, NetworkStream
    has Begin/EndRead functions for overlapped IO?)

    If anyone can shed some light on this, and perhaps even have a sample hanging
    around, i'd appreciate it.


  2. #2
    GJ Guest

    Re: C# and ThreadPools


    DO NOT use a thread pool to handle sockets... Use Async I/O instead... Here's
    why:

    The thread pool in .net is optimized so that it won't always spawn a new
    thread immediately when one is blocking. So if you have enough sockets, your
    threadpool will stall, causing your entire app to stall (if you use thread
    pool for other stuff), until some of the threads unblock. Trust me, I've
    been dealing with this for a long time.

    Anyways, now for the info:

    To use a thread pool to handle sockets, this how you can do it... Have one
    thread spin through your list of sockets. Poll the socket for data, and return
    immediately. If data is present, QueueUseWorkItem the socket and remove it
    from the list. In the callback, type cast the state object to a socket, and
    issue a blocking send. when it returns, process the data. Then stick the
    socket back in the list... Rinse-repeat...

    The caveat to this, is that this one thread spinning through your list, polling
    for data, is a thread owned by you. So the finalizer will not be called until
    you destroy this thread. (hence another reason to use Async I/O)

    Anyways, this will work in most situations, until you get lots of sockets,
    and many of them start blocking for prolonged period of time. This caused
    the system threadpool to stop spawning threads until some of them unblock.
    I've found that it does this sequentially... This makes using a thread-pool
    to do this stupid....

    Instead do this:

    do a BeginAccept/EndAccept to do an async connect. In the callback, do a
    BeginReceive/BeginAccept

    in the receive callback, process data, and issue another BeginReceive.
    Be sure to trap the appropriate exceptions... If you do this, you'll find
    performance to be MUUUUUUUUCH better.... I've implemented my base class
    this way, and I've pounded it in testing, and it performed really really
    well.

    (NOTE: Async I/O and Threadpools are only supported in Win2000/XP)


    "Erik Funkenbusch" <erikf@visi.com> wrote:
    >
    >Ok, i've been trying to wrap my head around ThreadPools being used with

    C#,
    >and it just keeps getting lost somewhere. Specifically I want to use ThreadPools
    >to service Socket connections.
    >
    >From what I read, I can bind a socket handle to a ThreadPool, but it makes
    >no sense as to how to make this call the correct callback when data comes
    >in.
    >
    >Most of the samples i've found for ThreadPools only use QueueUserWorkItem.
    > Some of the use RegisterWaitForSingleObject. Now, it seems like I could
    >use RegisterWaitForSingleObject, but you have to create the socket as overlapped,
    >however, TcpListen does the creation of the socket for you and doesn't appear
    >to have an option to create the socket overlapped (though oddly enough,

    NetworkStream
    >has Begin/EndRead functions for overlapped IO?)
    >
    >If anyone can shed some light on this, and perhaps even have a sample hanging
    >around, i'd appreciate it.
    >



  3. #3
    GJ Guest

    Re: C# and ThreadPools


    I neglected to read your post farther... I used straight Sockets... I don't
    bother with TcpClient, UdpClient, etc etc... Reminds me of CSocket and CAsyncSocket,
    which were lame implementations... Just used straight Winsock instead...

    Just use the Socket class, it's not that hard actually... You'll find it
    to be much more powerful/flexible...

  4. #4
    Erik Funkenbusch Guest

    Re: C# and ThreadPools


    Hmm.. I think you're doing something wrong if your threads are blocking in
    thread pools. The whole point of a thread pool is that when data is received,
    your thread pool notices it and executes your callback function, which should
    only take the data you've received and do something with it, *NOT* block
    waiting for data.

    There shouldn't be any reason for your thread pool to block at all, and it
    gains the advantage that as you add more processors, it scales with it.
    If your thread needs to do something that blocks, it should probably spawn
    a worker thread for that.

    I'm trying to minimize the number of threads used, and your approach just
    keeps spanwing new threads, which is very inneficient (though you may find
    it to work well for you).

    "GJ" <star_screamer@hotmail.com> wrote:
    >
    >DO NOT use a thread pool to handle sockets... Use Async I/O instead... Here's
    >why:
    >
    >The thread pool in .net is optimized so that it won't always spawn a new
    >thread immediately when one is blocking. So if you have enough sockets,

    your
    >threadpool will stall, causing your entire app to stall (if you use thread
    >pool for other stuff), until some of the threads unblock. Trust me, I've
    >been dealing with this for a long time.
    >
    >Anyways, now for the info:
    >
    >To use a thread pool to handle sockets, this how you can do it... Have one
    >thread spin through your list of sockets. Poll the socket for data, and

    return
    >immediately. If data is present, QueueUseWorkItem the socket and remove

    it
    >from the list. In the callback, type cast the state object to a socket,

    and
    >issue a blocking send. when it returns, process the data. Then stick the
    >socket back in the list... Rinse-repeat...
    >
    >The caveat to this, is that this one thread spinning through your list,

    polling
    >for data, is a thread owned by you. So the finalizer will not be called

    until
    >you destroy this thread. (hence another reason to use Async I/O)
    >
    >Anyways, this will work in most situations, until you get lots of sockets,
    >and many of them start blocking for prolonged period of time. This caused
    >the system threadpool to stop spawning threads until some of them unblock.
    >I've found that it does this sequentially... This makes using a thread-pool
    >to do this stupid....
    >
    >Instead do this:
    >
    >do a BeginAccept/EndAccept to do an async connect. In the callback, do a
    >BeginReceive/BeginAccept
    >
    >in the receive callback, process data, and issue another BeginReceive.
    >Be sure to trap the appropriate exceptions... If you do this, you'll find
    >performance to be MUUUUUUUUCH better.... I've implemented my base class
    >this way, and I've pounded it in testing, and it performed really really
    >well.
    >
    >(NOTE: Async I/O and Threadpools are only supported in Win2000/XP)
    >
    >
    >"Erik Funkenbusch" <erikf@visi.com> wrote:
    >>
    >>Ok, i've been trying to wrap my head around ThreadPools being used with

    >C#,
    >>and it just keeps getting lost somewhere. Specifically I want to use ThreadPools
    >>to service Socket connections.
    >>
    >>From what I read, I can bind a socket handle to a ThreadPool, but it makes
    >>no sense as to how to make this call the correct callback when data comes
    >>in.
    >>
    >>Most of the samples i've found for ThreadPools only use QueueUserWorkItem.
    >> Some of the use RegisterWaitForSingleObject. Now, it seems like I could
    >>use RegisterWaitForSingleObject, but you have to create the socket as overlapped,
    >>however, TcpListen does the creation of the socket for you and doesn't

    appear
    >>to have an option to create the socket overlapped (though oddly enough,

    >NetworkStream
    >>has Begin/EndRead functions for overlapped IO?)
    >>
    >>If anyone can shed some light on this, and perhaps even have a sample hanging
    >>around, i'd appreciate it.
    >>

    >



  5. #5
    Erik Funkenbusch Guest

    Re: C# and ThreadPools


    Do you have any evidence which suggests that TcpClient is not acceptable?
    Or is this just your assumption based on CSocket? I agree that CSocket
    bites the big one, but I've found TcpClient to be quite nice.



    "GJ" <star_screamer@hotmail.com> wrote:
    >
    >I neglected to read your post farther... I used straight Sockets... I don't
    >bother with TcpClient, UdpClient, etc etc... Reminds me of CSocket and CAsyncSocket,
    >which were lame implementations... Just used straight Winsock instead...
    >
    >Just use the Socket class, it's not that hard actually... You'll find it
    >to be much more powerful/flexible...



  6. #6
    GJ Guest

    Re: C# and ThreadPools


    eh???
    Didn't you read my post? I suggested against using a thread pool for socket
    operations. I said using Async I/O is much prefererred...

    Anyways, getting back to Threadpools, the method is called: QueueUserWorkItem,
    which suggests, you are putting work items into the queue... Whether they
    are blocking operations or non-blocking operations is irrelevent... In fact,
    they are assumed to be blocking/time consuming operations... If they were
    non-blocking/non time-consuming, there would be no point in spawning another
    thread, just use the same thread.

    Also you said that it is bad to keep spawning threads... That is obvious...
    Didn't I suggest Async I/O? Besides, if you already think spawning threads
    is bad, then why are you trying to spawn a new thread to do all your socket
    operations?

    Now getting back to TcpClient:

    Tcp client does a synchronous connect. If you specify a dns name, it does
    a syncronous resolve. Those are both bad for performance. You'll get much
    better results if you just stick with plain socket, and do an async connect,
    and async resolves... With TcpClient you can't specify socket options, which
    are sometimes important. It's also more tedious to try to determine simple
    states, like when the remote side disconnected. With plain sockets, you just
    raise an event when your async operations throw an exception, or return 0.
    I don't think it works the same with the Network Stream object. You can't
    poll a network stream either. (Not that you would need to, but hey, maybe
    you might)
    As for reading and writing to the stream, you can still do async read/write
    on the stream object, so I don't object to that...


  7. #7
    Erik Funkenbusch Guest

    Re: C# and ThreadPools


    Yes, I did read your response, but it doesn't make a lot of sense to me.

    "GJ" <star_screamer@hotmail.com> wrote:
    >
    >eh???
    >Didn't you read my post? I suggested against using a thread pool for socket
    >operations. I said using Async I/O is much prefererred...


    The problem I have with Async I/O is that, from my understanding, it must
    create a new thread, which is very expensive. ThreadPools don't create new
    threads for each I/O operation.

    >Anyways, getting back to Threadpools, the method is called:
    > QueueUserWorkItem,


    I'm aware of this, but that's not the part of ThreadPools that I'm talking
    about. I'm specifically talking about the mechanism MS designed to bind
    I/O Completion ports to ThreadPools for thread handling.

    Specifically, I'm talking about what's described in this article by Jeffery
    Richter in Scenario 4:

    http://www.microsoft.com/msj/default...499/newnav.htm

    I'm assuming that BindIoCompletionCallback has something to do with the BindHandle()
    method of the ThreadPool class (which simply has a "To be supplied" description).
    However, there doesn't seem to be a way to specify a callback function with
    this method.

    >which suggests, you are putting work items into the queue... Whether they
    >are blocking operations or non-blocking operations is irrelevent... In fact,
    >they are assumed to be blocking/time consuming operations... If they were
    >non-blocking/non time-consuming, there would be no point in spawning another
    >thread, just use the same thread.


    That's the point of ThreadPools. They DO NOT spawn new threads, unless all
    existing threads are busy and there are free processors. Thread Pools generally
    only allocate one thread per processor, and require that the threads don't
    block. If you do block, you have to tell the Thread Pool manager this, so
    it can spawn a new thread to deal with it (unfortunately, the ThreadPool
    implementation in the .NET framework doesn't seem to handle this).

    >Also you said that it is bad to keep spawning threads... That is obvious...
    >Didn't I suggest Async I/O? Besides, if you already think spawning threads
    >is bad, then why are you trying to spawn a new thread to do all your socket

    operations?

    I'm not. That's why i'm trying to use Thread Pools, because they don't spawn
    new threads. They keep a pool of threads to re-use.

    >Now getting back to TcpClient:
    >
    >Tcp client does a synchronous connect. If you specify a dns name, it does
    >a syncronous resolve. Those are both bad for performance. You'll get much
    >better results if you just stick with plain socket, and do an async connect,


    I'm not using TcpClient to connect, I'm using TcpListener to listen and accept
    connections. It only blocks if you call a blocking function. If you call
    BeginRead, it creates an Asynch I/O read. So I don't understand your complaint.
    You *CAN* do Asynch I/O with TcpClient.

    >and async resolves... With TcpClient you can't specify socket options, which
    >are sometimes important. It's also more tedious to try to determine simple
    >states, like when the remote side disconnected. With plain sockets, you

    just
    >raise an event when your async operations throw an exception, or return

    0.

    Yes, I can see your point about socket options. However, you have access
    to the underlying Socket, so I don't see why you can't set the options that
    way.

    >I don't think it works the same with the Network Stream object. You can't
    >poll a network stream either. (Not that you would need to, but hey, maybe
    >you might)
    >As for reading and writing to the stream, you can still do async read/write
    >on the stream object, so I don't object to that...


    Since you have access to the underlying socket, why can't you?




Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center