C
chris gouldie via .NET 247
I have a multiple part question about the thread safety of the
Socket class, and how asynchronous socket events occur. The
documentation of this class is misleading, but the behavior
is what I would expect (and want). Here is my interpretation
of the documentation:
When you call BeginReceive, the asynchronous callback you
specified is immediately called. This callback should call the
EndReceive function on the socket, which will block until data is
actually available.
I think my interpretation is a reasonable one given the docs. I will
quote them for you here:
For BeginReceive:
"When your application calls BeginReceive, the system will use a
separate thread to execute the specified callback method, and will
block on EndReceive until the Socket reads data or throws an
exception."
And for EndReceive:
"Before calling BeginReceive, you need to create a callback method
that implements the AsyncCallback delegate. This callback method
executes in a separate thread and is called by the system after
BeginReceive returns. [.....] The EndReceive method will block
until data is available."
For Thread Safety of the Socket class, the docs say:
"Any public static (Shared in Visual Basic) members of this type
are thread safe. Any instance members are not guaranteed to be
thread safe."
Therein lies the problem. First of all, the BeginReceive function
does not behave the way that the docs seem to imply. I do not
receive a callback immediately, I only receive a callback when there
is data to be read from the Socket. This is a Good Thing.
The reason this is a Good Thing, is that the Socket class is,
according to the docs, not thread safe. I interpret this to mean
that I must lock around any method calls on an instance of the
class. So, consider the following:
void MyReceiveCallBack(IAsyncResult aResult)
{
...
lock (sock)
{
int bytesRead = sock.EndReceive(aResult);
}
...
}
What happens if a thread in my application now calls a method which
contains the following code?
void MySendFunc(byte [] stuffToSend)
{
...
lock (sock)
{
aResult = sock.BeginSend(...);
}
...
}
That's right, I can't send until something is read from the socket!
Fortunately, the docs are incorrect, and what actually happens is
that I don't get a callback until there is data to be read. However,
I am still unhappy about having to lock around every method call
on the Socket instance. The docs should tell me HOW the class is
not thread safe. Just telling me that it isn't thread safe doesn't
help me at all. Is there something I am missing here? I'm worried
that someday Microsoft will release a patch to the framework that
causes Socket to behave the way that the docs say it will, and my
code will break. Help! Please!
Socket class, and how asynchronous socket events occur. The
documentation of this class is misleading, but the behavior
is what I would expect (and want). Here is my interpretation
of the documentation:
When you call BeginReceive, the asynchronous callback you
specified is immediately called. This callback should call the
EndReceive function on the socket, which will block until data is
actually available.
I think my interpretation is a reasonable one given the docs. I will
quote them for you here:
For BeginReceive:
"When your application calls BeginReceive, the system will use a
separate thread to execute the specified callback method, and will
block on EndReceive until the Socket reads data or throws an
exception."
And for EndReceive:
"Before calling BeginReceive, you need to create a callback method
that implements the AsyncCallback delegate. This callback method
executes in a separate thread and is called by the system after
BeginReceive returns. [.....] The EndReceive method will block
until data is available."
For Thread Safety of the Socket class, the docs say:
"Any public static (Shared in Visual Basic) members of this type
are thread safe. Any instance members are not guaranteed to be
thread safe."
Therein lies the problem. First of all, the BeginReceive function
does not behave the way that the docs seem to imply. I do not
receive a callback immediately, I only receive a callback when there
is data to be read from the Socket. This is a Good Thing.
The reason this is a Good Thing, is that the Socket class is,
according to the docs, not thread safe. I interpret this to mean
that I must lock around any method calls on an instance of the
class. So, consider the following:
void MyReceiveCallBack(IAsyncResult aResult)
{
...
lock (sock)
{
int bytesRead = sock.EndReceive(aResult);
}
...
}
What happens if a thread in my application now calls a method which
contains the following code?
void MySendFunc(byte [] stuffToSend)
{
...
lock (sock)
{
aResult = sock.BeginSend(...);
}
...
}
That's right, I can't send until something is read from the socket!
Fortunately, the docs are incorrect, and what actually happens is
that I don't get a callback until there is data to be read. However,
I am still unhappy about having to lock around every method call
on the Socket instance. The docs should tell me HOW the class is
not thread safe. Just telling me that it isn't thread safe doesn't
help me at all. Is there something I am missing here? I'm worried
that someday Microsoft will release a patch to the framework that
causes Socket to behave the way that the docs say it will, and my
code will break. Help! Please!