pedrito said:
In what way did you find it no "constructed clearly enough" I provided the
code. I showed precisely where the exception was occurring. The code is
happening in a try/catch handler, but the exception is taking place in a
callback thread that I have no control over. .NET is creating the callback
internally.
It's hard to even know where to start. All I can say at this moment,
without going back and deconstructing your previous posts, is that I did
not feel that the code you posted and the exception you posted appeared
to be at all related.
Your comment above reinforces that. Showing us the code for one thread,
and then telling us about an exception that happens in a completely
different thread tells us very little about either thread. If the
exception didn't occur in thread using the code you posted, then there's
really no assurance that the exception has anything to do with the code
that was posted.
If I have more time later, and you are really interested, I will see if
I can go through the post more carefully and provide better feedback.
The bottom line here is that all of us are busy. I am, you are,
everyone else is. While I think it's important for a community to help
those in need, this has to be balanced with the effort required to
address that need.
In the case of your post, I found that the effort required simply to try
to understand what you were trying to tell us exceeded my threshold of
tolerance, especially given that in such situations I often find myself
without an answer anyway, in spite of spending a lot of time trying to
decipher the post.
I don't know that everyone else had the same impression. But the lack
of any reply suggests that might be the case. There's a lot of other
smart, experienced folks reading this newsgroup and well-constructed
questions almost always get some kind of reply, even if it's just some
sort of educated guess.
Well, no, I wasn't trying to close the socket.
That's my point. The stack trace appears to be code that _is_ trying to
close the socket. Since you didn't do that, that's a problem. Find the
code that's trying to close the socket, and you likely will find your
culprit.
The socket is, I suspect,
getting closed by the web server, possibly unexpectedly. It happens.
Not really. That is, the _connection_ may be closed. But the web
server doesn't have the power to close your socket. Only you do. If
the connection closes, normally that causes an exception (actually, a
socket error WSAECONNRESET that gets thrown as a SocketException). But
the socket itself remains unclosed until you call Close() on it.
My app
doesn't expect a well-behaved server which is why there's a big try/catch
around the whole thing. But since the exception is happening on a .NET
framework callback that I have no control over, I can't catch that
exception. So how do I create an app that deals with poorly behaved servers
if that's the case.
My recollection is that there is not enough information in your previous
post to understand in what context the exception is occurring or why
your own code isn't involved.
Other than that, I don't have anything useful to offer at the moment.
My point is your second part. Your first part, "none can" is not a precise
answer because it's not "strictly true". My question was, and I think I was
pretty clear about it, what is the dillineation? Is it things that force
paints off the GUI thread? Is it accessing certain data within GUI controls?
Is there any guieline? You say, "practically everything," but again, not
specific.
My point is that you MUST assume that it's "none can", because Microsoft
offers no information about what can.
The only way in which it is reasonably "not strictly true" is when you
are calling your own methods in a derived class. For example, if you
inherit Form in your class, and then implement a method that doesn't
actually do anything with the inherited Form class. That method may
well be safe to call from another thread (assuming no other
synchronization issues, of course).
But other than situations like that, do not ever access an instance of a
class derived from Control on any thread other than the thread that owns
that instance.
I'm not trying to bitch here, really. I'm just pointing out that my question
was specifically what. It's okay to say you don't know. But that was my
question.
I don't know.
There. Now, just to reinforce what I'm saying above: you must remember
that practically all of the .NET Control-derived classes are basically
just wrappers to pre-existing unmanaged Windows control classes. Those
classes have no function-based API; all interaction with them is done
via window messages.
For example, consider TextBox. Whether you are retrieving the text from
the control, setting the text, changing the selection, hiding the
control, showing the control, enabling the control, disabling the
control, etc. that all goes through the window message system. There is
essentially nothing useful you can do with the control that doesn't in
some way go through the window message system. That imposes the
requirement that you only access the control from the thread that owns it.
Now, in unmanaged code, this is typically handled for you when you call
SendMessage(). That unmanaged function will automatically block the
calling thread and execute the necessary window procedure on the actual
owning thread. I'm not sure why .NET doesn't have a similar behavior;
this would be like just implicitly always calling Invoke() when necessary.
But the fact is, it doesn't. If you are interacting with one of these
Controls in any way, you pretty much always have to use Invoke() or
BeginInvoke() when doing so from a thread other than the one that owns
the Control.
No exceptions. None that are officially acknowledged, anyway.
Getting the dimensions and doing a comparison to see if the image is within
a certain size range. Probably not going to be a problem. But how do I know
that creating an Image object is thread safe? Is it? I've never read that it
isn't, but that's really what I was asking.
An Image object isn't a GUI object. You can do anything you want with
it, without worrying about cross-thread issues. It's if and when the
results of your operations on the Image object get passed to some object
that is a GUI object that you get into trouble.
If you don't do that, no worries. If you do, worries.
Now, none of that means that you can simply ignore cross-thread issues.
The issue with Control-derived classes is a special, particular one.
But you always need to worry about synchronization if you have data that
is being accessed by multiple threads. It's just that those worries are
different from the one that requires you to call Control.Invoke().
Ironically, even though it may not be required (see above regarding
calling your own methods that don't actually use the base class
members), often using Control.Invoke() or Control.BeginInvoke() is the
most straightforward way to ensure this synchronization. So it's easy
to get the issues confused. But do take care: they aren't the same issues.
[...]
Thanks for answering, and really, please do tell me what you think was
unclear about my original post and I'll try to clarify.
I don't have enough time (especially after writing this post
) to
review your previous post. But if I find time, I'll try to.
Pete