它是不好的做法,有我的图书馆摆脱抛出不是其他的东西方法OperationCancelledException
当CancellationToken.IsCancelRequested
检测到?
例如:
async Task<TcpClient> ConnectAsync(string host, int port, CancellationToken ct)
{
var client = new TcpClient();
try
{
using (ct.Register(client.Close, true))
{
await client.ConnectAsync(host, port);
}
// Pick up strugglers here because ct.Register() may have hosed our client
ct.ThrowIfCancellationRequested();
}
catch (Exception)
{
client.Close();
throw;
}
return client;
}
Run Code Online (Sandbox Code Playgroud)
取消后,这有可能抛出ObjectDisposedException
或NullReferenceException
取决于时间.(因为TcpClient.ConnectAsync()
在TcpClient.Close()
同时调用时可以抛出任何一个.)
现在,我可以解决这个问题:
async Task<TcpClient> ConnectAsync(string host, int port, CancellationToken ct)
{
var client = new TcpClient();
try
{
using (ct.Register(client.Close, true))
{
try
{
await client.ConnectAsync(host, port);
}
catch (Exception)
{
// These exceptions are likely because we closed the
// connection with ct.Register(). Convert them to
// OperationCancelledException if that's the case
ct.ThrowIfCancellationRequested();
throw;
}
}
// Pick up strugglers here because ct.Register() may have hosed our client
ct.ThrowIfCancellationRequested();
}
catch (Exception)
{
client.Close();
throw;
}
return client;
}
Run Code Online (Sandbox Code Playgroud)
同样在适用的调用层次结构的每一层:
async Task<TcpClient> ConnectSslStreamAsync(string host, int port, CancellationToken ct)
{
var client = await ConnectAsync(host, port, ct);
try
{
ct.ThrowIfCancellationRequested();
var sslStream = new SslStream(client.getStream());
using (ct.Register(sslStream.Close))
{
try
{
await sslStream.AuthenticateAsClientAsync(...);
}
catch (Exception)
{
// These exceptions are likely because we closed the
// stream with ct.Register(). Convert them to
// OperationCancelledException if that's the case
ct.ThrowIfCancellationRequested();
throw;
}
}
// Pick up strugglers here because ct.Register() may have hosed our stream
ct.ThrowIfCancellationRequested();
}
catch (Exception)
{
client.Close();
throw;
}
return client;
}
Run Code Online (Sandbox Code Playgroud)
但是,实际上,所需要的只是在外层进行一次检查,这就增加了这些额外的代码.(在取消来源.)
让这些任意例外飞行是不好的做法?或者在最外面的来电者常规中忽略它们?
归档时间: |
|
查看次数: |
379 次 |
最近记录: |