gpt4 book ai didi

c# - 设置 CancellationToken 时抛出任意异常是不好的做法吗?

转载 作者:太空狗 更新时间:2023-10-29 23:37:17 29 4
gpt4 key购买 nike

当检测到 CancellationToken.IsCancelRequested 时,通过抛出 OperationCancelledException 以外的内容来让我的库中断方法是否是一种不好的做法?

例如:

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;
}

取消后,可能会抛出 ObjectDisposedExceptionNullReferenceException,具体取决于时间。 (因为 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;
}

同样在适用的调用层次结构的每一层:

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;
}

但这会添加这些额外的代码,而实际上,所需要的只是在最外层进行一次检查。 (在取消来源处。)

让这些任意异常飞起来是不好的做法吗?或者在最外层的调用者处忽略它们?

最佳答案

如果请求取消,您应该抛出 OperationCancelledException。当您的代码的使用者遇到异常时,他们将不知道这实际上是取消还是其他原因。

也就是说,如果您因为注册关闭委托(delegate)而无法抛出 OperationCancelledException,您可以尝试提供的方法 here您将在其中创建用于关闭 tcpClient 或流的任务,并验证哪个任务首先完成并采取相应的措施。

关于c# - 设置 CancellationToken 时抛出任意异常是不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37543144/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com