[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.dotnet.framework

sockets : Writing and reading on the same thread with events ?

Alessandro De Simone

11/15/2008 4:34:00 PM

Hello,

I have to exchange data on a socket within a unique thread in dotnet.

My idea is to use a queue for writing requests and a ManualResetEvent to
detect in the socket thread when one (or more) elements are added (from
the main thread) to the queue (look at my pseudo code bellow).

But is it possible to obtain a WaitHandle to detect when there is data
available for reading in the socket ? I know I can use the
"System.IAsyncResult.AsyncWaitHandle" from a "BeginRead", but this
method use an another thread.

In Win32, you could use "WSACreateEvent" and "WSAEventSelect" to get a
HANDLE used in "WaitForMultipleObjects".

Am I missing something ? Thanks :-)

Alessandro


---
WaitHandle[] ReadWrite = new WaitHandle[]{SocketReadEvent, QueueEvent};

while( 1 )
{
int index = WaitHandle.WaitAny(ReadWrite);

if( index == 0 )
{
// read an information (size is known) from the socket
}
else
{
// write the queue content on the socket
}
}
4 Answers

Peter Duniho

11/15/2008 10:21:00 PM

0

On Sat, 15 Nov 2008 08:34:15 -0800, Alessandro De Simone
<askmeformymail@thanks.com> wrote:

> Hello,
>
> I have to exchange data on a socket within a unique thread in dotnet.

Why? That's an unusual requirement, to say the least.

> My idea is to use a queue for writing requests and a ManualResetEvent to
> detect in the socket thread when one (or more) elements are added (from
> the main thread) to the queue (look at my pseudo code bellow).
>
> But is it possible to obtain a WaitHandle to detect when there is data
> available for reading in the socket ? I know I can use the
> "System.IAsyncResult.AsyncWaitHandle" from a "BeginRead", but this
> method use an another thread.

You have to provide a callback, but there's no rule that says you have to
do anything in the callback. You could just pass an empty anonymous
method, and wait on the handle you get from the IAsyncResult.

I guess for me the real question is why is it so important that you read
and write on the same thread? The Socket class itself is thread-safe, so
you can write from one thread and read from another. Or you can just use
the callback for BeginReceive(). There's nothing in your post that
suggests a need for the requirement you've stipulated, so it seems to me
that meeting that requirement is putting the cart before the horse.

Pete

Alessandro De Simone

11/16/2008 12:51:00 PM

0

Thanks for the answer.

> You have to provide a callback, but there's no rule that says you have
> to do anything in the callback. You could just pass an empty anonymous
> method, and wait on the handle you get from the IAsyncResult.

Correct me if I'm wrong, but the BeginReceive method use another thread
even when you don't specify a callback. The callback is just a delegate
called at the end of the thread (potentially in another different
thread!). Because you have to call EndReceive, most of the time the
callback is very useful.

> I guess for me the real question is why is it so important that you read
> and write on the same thread? The Socket class itself is thread-safe,
> so you can write from one thread and read from another. Or you can just
> use the callback for BeginReceive(). There's nothing in your post that
> suggests a need for the requirement you've stipulated, so it seems to me
> that meeting that requirement is putting the cart before the horse.

I want to have a minimum overhead in my application. I don't need to
send and read data at the same precise time. I make the assumption that,
most of the time (but not every time), a client send a message and wait
for an answer before sending another.

So, if a second thread isn't necessary, why should I use it ? I don't
want to use a second thread (for every read operations) only to obtain a
handle with which I can wait the event "Data Available". The synchronous
"Receive" already wait for this kind of event when the protocol stack
buffer is empty.

I my opinion, my solution is pretty simple (and feasible on Win32).

Now if you are sure that's impossible to have a simple event "Data
available on socket" with DotNet, I will use BeginReceive unwillingly...

Thanks :-)

Michael D. Ober

11/16/2008 7:13:00 PM

0

"Alessandro De Simone" <askmeformymail@thanks.com> wrote in message
news:4920172c$0$2858$ba620e4c@news.skynet.be...
> Thanks for the answer.
>
>> You have to provide a callback, but there's no rule that says you have to
>> do anything in the callback. You could just pass an empty anonymous
>> method, and wait on the handle you get from the IAsyncResult.
>
> Correct me if I'm wrong, but the BeginReceive method use another thread
> even when you don't specify a callback. The callback is just a delegate
> called at the end of the thread (potentially in another different
> thread!). Because you have to call EndReceive, most of the time the
> callback is very useful.
>
>> I guess for me the real question is why is it so important that you read
>> and write on the same thread? The Socket class itself is thread-safe, so
>> you can write from one thread and read from another. Or you can just use
>> the callback for BeginReceive(). There's nothing in your post that
>> suggests a need for the requirement you've stipulated, so it seems to me
>> that meeting that requirement is putting the cart before the horse.
>
> I want to have a minimum overhead in my application. I don't need to send
> and read data at the same precise time. I make the assumption that, most
> of the time (but not every time), a client send a message and wait for an
> answer before sending another.
>

Don't worry about the threading. The framework pulls the threads out of the
thread pool. If your communications are indeed slow, the threadpool won't
create additional threads. However, if you do have a communications burst,
the threadpool will increase the number of threads available for the Async
callbacks and then, later, kill some of the threads when they are no longer
needed.

> So, if a second thread isn't necessary, why should I use it ? I don't want
> to use a second thread (for every read operations) only to obtain a handle
> with which I can wait the event "Data Available". The synchronous
> "Receive" already wait for this kind of event when the protocol stack
> buffer is empty.
>
> I my opinion, my solution is pretty simple (and feasible on Win32).
>

Actually, I had the same issues when I switched from Win32/MFC CSocket
programming, which makes it easy to put your sockets handlers on a single
thread. The real issue you will need to deal with in dotNet is that
everything uses async threading, so you'll need to start thinking about
multi-threading (and multi-processor) issues such as synchronization.

> Now if you are sure that's impossible to have a simple event "Data
> available on socket" with DotNet, I will use BeginReceive unwillingly...
>
> Thanks :-)
>

Mike.


Peter Duniho

11/16/2008 9:00:00 PM

0

On Sun, 16 Nov 2008 04:50:42 -0800, Alessandro De Simone
<askmeformymail@thanks.com> wrote:

> Thanks for the answer.
>
>> You have to provide a callback, but there's no rule that says you have
>> to do anything in the callback. You could just pass an empty anonymous
>> method, and wait on the handle you get from the IAsyncResult.
>
> Correct me if I'm wrong, but the BeginReceive method use another thread
> even when you don't specify a callback.

As I mentioned, you _must_ provide a callback. But you're right, the
callback will almost always occur on a different thread than that used to
call BeginReceive().

> The callback is just a delegate called at the end of the thread
> (potentially in another different thread!). Because you have to call
> EndReceive, most of the time the callback is very useful.

You don't have to call EndReceive() in the callback. If you are waiting
on the event handle returned by the IAsyncResult returned by the call to
BeginReceive(), you can simply call EndReceive() in that same thread.

>> I guess for me the real question is why is it so important that you
>> read and write on the same thread? [...]
>
> I want to have a minimum overhead in my application.

Do not make premature optimizations. They often wind up pointless or even
counter-productive, and they cost you development time (design, coding,
testing, the whole works).

> I don't need to send and read data at the same precise time. I make the
> assumption that, most of the time (but not every time), a client send a
> message and wait for an answer before sending another.

How many connections will you have? If just one, then there is no
performance optimization you can make that will matter when it comes to
network i/o. The cost of the network i/o itself (i.e. the bandwidth of
the actual network connection) is so much higher than that of any code
that will handle moving the data into or out of that connection that
optimizing the latter is pointless.

If (a great deal) more than one, then you must have either a single thread
managing multiple connections, or you've got one of these threads per
connection. In which case your optimization would be counter-productive.
The asynchronous Socket methods use IOCP with a dedicated thread pool, and
they are there precisely because that's the most efficient way to deal
with network i/o.

> So, if a second thread isn't necessary, why should I use it ?

Because it makes your design simpler and works better with the framework's
intent. The fact is, one extra thread is not going to produce a
significant difference in performance at all, and that's assuming there
really is an extra thread (sometimes there would be, sometimes there won't
be...it depends on what else is going on in the process). There's
absolutely no point in wasting time and energy contorting your
application's design to try to avoid that one extra thread. At best, it's
a waste of your time, and at worst it could actually reduce your
application's performance.

Pete