Why are async callback socket methods usually static? (assume I understand static class, method and data objects). Would there be a fundamental design/logic error if one were to write a class using these as instance methods? Is there anything special that one should be careful to avoid?
Callback functions are usually static because you don't know what anything about the class that you are making a call back on.
In fact a class instance function usually carries the "this" pointer as a hidden first parameter.
See: http://www.drdobbs.com/184403375;jsessionid=P5JGJLQBDYGWBQE1GHOSKH4ATMY32JVN?pgno=2
Edit: Also see http://stackoverflow.com/questions/2400690/why-callback-functions-needs-to-be-static-when-declared-in-class
At least in C++, a non-static method expects to receive this
as a hidden parameter. Since whatever's invoking it as a callback doesn't know that, it won't pass that extra parameter. If you did manage to invoke a non-static member function as a callback, anything that attempted to use member data (which would happen via this
) would (almost certainly) have major problems.
I'd guess C# is at least somewhat similar, though I haven't studied the details enough to know for sure. Regardless of language, the code needs to know what data to work with. The obvious difference is that C# also supports delegates, which are extremely useful for callbacks.
Edit: as to how to avoid this, at least in C++ it's fairly simple. You'd typically want to use a library like ACE, Boost ASIO, or POCO that shields you from most of the messy details. If you do some looking around, you can probably find at least a few dozen others as well. Oh, I should add that most of the application framework-style libraries (e.g., wxWidgets and Qt) include classes to shield you from most of the messy details as well. The obvious difference is that these tend to "take over" the design of the application in general (though, in fairness, I should add that ACE tends a bit toward the same).
Of course, people have written libraries for C# as well, but I haven't used any enough to make a meaningful recommendation about them. A lot here also depends on the level of abstraction you're looking for. WCF (for example) does quite a bit more than just shield you from the messy details. Rather, it builds essentially its own complete idea of how to work with networks, that happens to (somewhere in there) be able to use sockets -- but for the most part, you're not really working with sockets anymore, you're working with WCF, which happens to use sockets.
Ultimately, however, the library is just hiding, not changing, what really happens. Somewhere inside the library, Winsock makes a callback to either a static member function or a free function that uses the basic C calling convention that it expects. That function then uses extra data (usually the parameter that's passed to it) to figure out what to invoke from there. What varies is how thick a layer of "insulation" there is between your code and the callback from Winsock.
They are usually static because it is usually hard to write a good software, especially well designed library for asynchronous I/O in C++. Otherwise they are not static at all. Take a look at Boost.ASIO. It is by far the best library for asynchronous operations for C++.
As for the C language, there is no such thing as static method because there are no methods :-) But those callback usually provide you with an option to pass addition data trough the "void *" pointer that will be given you back on callback. Using that, you can write object-oriented code in C. In the most basic C++ example of asynchronous I/O the C language is used. That is why you might think this is a common case. For C it is.
There is no specific reason that they should be static. It all depends on your design.
If the callback needs to access members in the class then it can be declared as a instance member. However, you will need to make sure that you correctly syncronize the access to the instance members because the callback can be invoked concurrently from different threads.
I guess the examples you looked at all passed the required data through to the callback through the IAsyncResult.AsyncState
so did not require additional information from the class. If you can do this it can simplify your code, since you no longer need to worry about thread syncronization etc..
Update
Just to clarify, based on the comments it seems I should have beed more explicit. It is not that the static callback would be thread safe, but rather that in a design where the data required is passed to the callback and of course this data is not shared by other threads then locking is not required. And since the callback is passed all the data it requires, it does not need access to the class instance and can therefore be made static.