Fix `Socket.ConnectAsync(SocketAsyncEventArgs)` behavior. (#15947)
We need to clearly distinguish between synchronous and asynchronous completions
and avoid any ambiguities and race conditions when it comes to error handling.
On synchronous completion, we must not invoke the async completion delegate.
In `System.Net.Sockets/Socket.cs`, the internal `BeginSConnect()` and `BeginMConnect()`
now return a `bool` indicating whether or not an async operation is pending.
If any error happens prior to starting the async operation, then we shall call
`SocketAsyncResult.Complete(..., true)` and return `false`. And since this is
a synchronous completion, it's `AsyncCallback` will not be invoked.
In `referencesource/System/net/System/Net/Sockets/_MultipleConnectAsync.cs`,
I compared the entire file against the CoreFX version and then copied the
`AttemptConnection()` method from their implementation to adapt their behavior.
The difference is that on synchronous completion, the `InternalConnectCallback(null, args)`
should be invoked.