我正在尝试设计一个允许使用 TcpClient 类连接和发送/接收命令的邮件客户端服务。我还想在每个函数的回调时自动调用调用线程,这样调用者就不需要了。
我发现我需要为每个函数编写至少三到四倍的代码才能实现这一点,而不是同步编写它。最大的问题是我必须为每个回调编写单独的 try/catch。
我将发布我的 Connect 功能,希望有人可以提出更好的方法:
public virtual void Connect(Action<Exception> callback, string hostname, int port, bool ssl, RemoteCertificateValidationCallback validateCertificate)
{
if (State != ConnectionState.Disconnected)
throw new InvalidOperationException(AlreadyConnectedString);
Host = hostname;
Port = port;
Ssl = ssl;
var context = SynchronizationContext.Current;
// Callback on the caller's thread
Action<Exception> onCallback = (Exception ex) =>
{
context.Post(_ =>
{
callback(ex);
}, null);
};
// Called on any raised exceptions
Action<Exception> onFail = (Exception ex) =>
{
State = ConnectionState.Disconnected;
Cleanup();
onCallback(ex);
};
// Check for a valid response
Action<string, Exception> onConnectResponse = (string response, Exception ex) =>
{
if (ex != null)
onFail(ex);
try
{
OnConnected(response);
onCallback(ex);
}
catch (Exception responseException)
{
onFail(responseException);
}
};
// Callback after SSL authentication
AsyncCallback onAuthenticated = (IAsyncResult result) =>
{
try
{
var sslStream = (SslStream)result.AsyncState;
sslStream.EndAuthenticateAsClient(result);
State = ConnectionState.Authorization;
GetResponse(onConnectResponse);
}
catch (Exception authenticateException)
{
onFail(authenticateException);
}
};
// Callback after TcpClient connect
AsyncCallback onConnect = (IAsyncResult result) =>
{
try
{
_Connection.EndConnect(result);
_Stream = _Connection.GetStream();
if (ssl)
{
SslStream sslStream;
if (validateCertificate != null)
sslStream = new SslStream(_Stream, false, validateCertificate);
else
sslStream = new SslStream(_Stream, false);
_Stream = sslStream;
sslStream.BeginAuthenticateAsClient(hostname, onAuthenticated, sslStream);
}
else
{
State = ConnectionState.Authorization;
GetResponse(onConnectResponse);
}
}
catch (Exception connectException)
{
onFail(connectException);
}
};
try
{
_Connection = new TcpClient();
_Connection.BeginConnect(hostname, port, onConnect, null);
}
catch (Exception ex)
{
onFail(ex);
}
}