30 August 2004
A few suggestions from playing with Kristin's PowerBook for a few days. Many of these come from my Windows background, but I think that they're cases of Windows doing it better – not simply a desire for what I'm used to.
- Remove the distinction between active applications and open documents.
- It's confusing to have an application continue running after you've closed its last window. Especially when the only indication of this is an arrow at the bottom of a dock icon. Also, this distinction means that you can't option-tab through different windows from the same application and leads to the “invisible sheets” that Joel on Software mentions (scroll down to the Mac screenshots). Implementing this suggestion would allow access to the desktop without needing an explicitly active Finder (which would appear only if a folder window were open).
- Enlarge the traffic lights in the right of every window titlebar.
- For a company with menus designed around Fitts's law, these sure are tiny controls. It might be tough to fit bigger buttons into the slick title bars, but it needs to be done. AskTog has a more comprehensive discussion of the gumdrops (is that the official name?).
- Allow maximization of a window.
- For when we want to focus on a single document. And this means that the scroll bars should be usable by throwing the mouse cursor against the right side of the screen. And that the dock should somehow get out of the way.
- Address these nine reasons why the dock still sucks.
- Another good column from AskTog.
- Add another mouse button.
- I know that this is a long-running debate, but even Jef Raskin, designer of the Mac, says that there should have been two-buttons on the Mac mouse. As mentioned at the end of this Wired article, the context-menus should be accessible from a mouse button, not a modified click.
- Create an extended menu of programs and documents.
- A Mac hard-drive is better organized than a Windows one, but I shouldn't have to open it to launch a program that didn't fit in the dock. Something like the Windows Start menu, or something better than the Start menu (I'm referring to DragThing) would be great.
Do you have any other suggestions?
05 August 2004
Here are a some bugs and subtleties in the .NET System.Sockets.Net library (or documentation) that have burned me while doing C# development.
Network programming isn't easy, but Microsoft's poor implementation and
documentation of these classes make it even harder.
- TcpClient.Close()
doesn't close the socket connection.
- This is apparently by design, though you won't find that anywhere in the
documentation (until Whidbey and version 2.0 of the .NET Framework). When you call TcpClient.GetStream(), the returned NetworkStream becomes the
owner of the underlying socket. To close the socket, call
TcpClient.GetStream().Close(). TcpClient.Close() should work if you never
called GetStream(), but I wouldn't count on that behavior continuing in Whidbey.
In fact, I'm not sure what the .NET 2.0 version of TcpClient.Close() does. Isn't
the socket the only resource that needs to be disposed of?
- Socket.Available
and NetworkStream.DataAvailable
don't throw exceptions when the socket connection dies.
- The
documentation wrongly says that these properties will throw a
SocketException if “the remote host shuts down or closes the
connection.” In fact, the documentation of the Winsock function
ioctlsocket(sock,
FIONREAD, &argp) (which these properties wrap) says that an
error is returned (and thus an exception thrown) only in a few rare cases
(namely WSANOTINITIALISED 10093 if WSAStartup was never called,
WSAENETDOWN 10050 if the network is down or the network stack is full,
WSAEINPROGRESS 10036 if another blocking operation is in progress,
WSAENOTSOCK 10038 if the file descriptor is not a socket, and WSAEFAULT
10014 if argp is an invalid pointer) and not if the socket simply disconnects.
Also, you shouldn't rely on the accuracy of the number returned from
Socket.Available (see Microsoft
Knowledge Base Article #192599 for details).
- Socket.Connected
doesn't check that the socket is currently connected, only that it was as of the
last IO operation.
- That is, this propery never tells you anything you didn't already know. If
your socket never connected, it's not connected. If your last call to send or
receive threw something other than WSAEWOULDBLOCK 10035, the socket
isn't connected. Etc. The .NET 2.0 documentation suggests a dance involving
messing with the socket's blocking mode and sending zero bytes over it, but that
doesn't work either.
The only reliable way to detect a network disconnection is by reading or writing
to the Socket (or TcpClient, or whatever). By default, those are blocking
operations. You'll need to either use the asynchronous BeginReceive and
BeginSend or BeginRead and BeginWrite (but be sure to check for exceptions
thrown by the corresponding End function); make your socket non-blocking, call
Socket.Poll or Socket.Select before sending or receiving, or do your socket
operations on their own thread. Again, network programming is not a trivial
task. I hope this had made it a little easier.
If you've had any other problems with these socket libraries, or have any
other suggestions for working around them, let me know. For other problems
with .NET, check out this helpful list of .NET bugs. If ever a
.NET function doesn't do what you expect, look through its source with the .NET Reflector, which I used
to help solve these socket problems.
Josh Ledgard ("chief community evangelist" for Visual Studio) talks about the MSDN product feedback center.