Question about multi-threading

D

Diego F.

Hello. I have a doubt about multi-threading, if it is or not the best way to
achieve the following:

I have a server application that listens a port through a socket.
A client will send messages to that application (many messages).
Because the amount of messages is huge, the server application should only
send each received message to another process (a thread?) that manages the
message, and then go with the next message.

I want a limited number of threads, so the server app just looks for one
that is free and send the message to it. Once the threads finish the work,
they wait to be called by the server app.

Are threads the solution for that?




Regards,

Diego F.
 
N

Nicholas Paldino [.NET/C# MVP]

Diego,

Yes, I believe they are, but you will need to hold off on accepting new
or processing new messages (the semantics are up to you) until the previous
ones complete.

Are you locked into the protocol that you are using for requests from
the clients, or are you able to dictate what the message format is? If so,
I would recommend using WCF to handle the communications (you can use a Tcp
connection for the transport and a binary encoder for the format of the
messages) as it has this kind of tuning built in.

If the format of the messages is locked, and you have to implement this
custom, you still might want to create a custom transport in WCF on the
service side as well as a custom encoder, and allowing WCF to handle all the
plumbing involving threading and the like.

Hope this helps.
 
P

Peter Duniho

Diego F. said:
I have a server application that listens a port through a socket.
A client will send messages to that application (many messages).
Because the amount of messages is huge, the server application should only
send each received message to another process (a thread?) that manages the
message, and then go with the next message.

I want a limited number of threads, so the server app just looks for one
that is free and send the message to it. Once the threads finish the work,
they wait to be called by the server app.

Are threads the solution for that?

Sure. Rather than "send each received message to another process", I might
write "enqueue each received message to another thread".

Assuming that the order of processing is unimportant, it seems to me that an
easy solution is to use the BackgroundWorker class. With this, .NET manages
your pool of threads. You can add a task to the pool, and if there's a
thread available to work on the task, it is assigned the task and runs. If
all of the threads are already busy, your task is kept in a queue until
there's a thread available.

In this paradigm, a "task" is represented simply as a delegate which you add
to the BackgroundWorker's DoWork event. You can pass unique data to the
RunWorkerAsync() method, and extract that data from the Argument property of
the DoWorkEventArgs passed into your DoWork delegate. The call to
RunWorkerAsync() enqueues your task, and when there's a thread available to
run the task, your DoWork delegate is called for the actual processing.

I read the reply from Nicholas recommending the use of WCF for this purpose.
I have to admit, I don't know anything about WCF and maybe it has this sort
of thing built right into it. If it is, maybe Nicholas could be a bit more
explicit as to what part of WCF would be useful for doing this sort of
data-processing delegation.

Pete
 
N

Nicholas Paldino [.NET/C# MVP]

Peter,

Assuming that the OP can rewire the client and server to use WCF, it
would be a good fit here. In particular, I'm assuming that the OP would
want to use the TCP binding in WCF.

With WCF, at least for the Tcp binding, you can set the ListenBacklog
and MaxPendingAccepts properties in the config file (and through code, if
you prefer).

The ListenBacklog property will allow you to set the maximum number of
queued connection requests that can be pending, while the MaxPendingAccepts
property indicates the maximum number of concurrent accepting threads on the
endpoint will have.
 
P

Peter Duniho

Nicholas Paldino said:
[...]
The ListenBacklog property will allow you to set the maximum number of
queued connection requests that can be pending, while the
MaxPendingAccepts property indicates the maximum number of concurrent
accepting threads on the endpoint will have.

It's not clear to me that that's what the OP wants. You seem to be talking
about having control over the lower-level aspects of making TCP connections,
while the OP's question seems to me to just be talking about separating his
i/o (the network communications) from the processing (the act of "managing
the message").

Do I misunderstand the original post, or is there something in WCF that is
particularly suited to addressing the latter?

Pete
 
N

Nicholas Paldino [.NET/C# MVP]

Peter,

The OP wants to have a limited number of threads to process incoming
requests that come in on a port. This is what WCF is doing with the
MaxPendingAccepts property. It basically says "hey, you can have

The thing is, while the client is only going to process a limited number
of calls, the OP will still have to worry about queuing the incoming calls
that will come in while his service is running. Then, when the operations
are done, the OP also has to worry about dispatching those requests.

That's where the ListenBacklog property will come in, as it will
indicate how many pending requests can be backlogged before requests are
starting to be turned away (the OP might want to turn this way up).

The reason to recommend WCF in this case is because it handles all of
this for you. You just have to define your interface, and code against it
(within the model, of course). WCF will handle listening for the request,
managing how many requests are processed at the same time, denying other
requests if too many are coming in, etc, etc for you. The OP is going to
have to worry about this himself if he codes it from scratch.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Peter Duniho said:
Nicholas Paldino said:
[...]
The ListenBacklog property will allow you to set the maximum number of
queued connection requests that can be pending, while the
MaxPendingAccepts property indicates the maximum number of concurrent
accepting threads on the endpoint will have.

It's not clear to me that that's what the OP wants. You seem to be
talking about having control over the lower-level aspects of making TCP
connections, while the OP's question seems to me to just be talking about
separating his i/o (the network communications) from the processing (the
act of "managing the message").

Do I misunderstand the original post, or is there something in WCF that is
particularly suited to addressing the latter?

Pete
 
C

Chris Mullins [MVP]

There are a number of different architectures available for you to pick
from. In general, the best architecture for building a "big" socket
application is to use Async Sockets, and let Windows (and the CLR) manage
the majority of your threading for you. If possible, you should avoid
creating and managing your own threads as there's alot of complexity
inherent in doing so.

I build big socket servers for a living, and some time ago I wrote up a
bunch of the architectural iterations that I've been through when doing this
in .Net.

http://www.coversant.com/Coversant/Blogs/tabid/88/EntryID/10/Default.aspx
 
P

Peter Duniho

Nicholas Paldino said:
Peter,

The OP wants to have a limited number of threads to process incoming
requests that come in on a port. This is what WCF is doing with the
MaxPendingAccepts property. It basically says "hey, you can have

I think you left out some words. :)

As far as "wants to have a limited number of threads to process incoming
requests that come in on a port" goes...

I admit to not being familiar with WCF, but if I read the docs right, using
the ListenBackLog property assumes that each request is made with a new TCP
connection. It's equivalent to the "backlog" parameter of Socket.Listen().
I don't read the original post as asking for that functionality (and
frankly, I don't really see how WCF provides significantly easier access to
that functionality than simply setting it using the plain Socket.Listen()
method).

I guess only the OP can really clear this up, as it comes down to a
disagreement as to what he actually meant. Hopefully between the two of us,
someone's provided him with a useful answer. :)

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top