在使用 ChannelWriter 的 SignalR Core 中:如果出现异常,是否需要调用 TryComplete 两次?
In SignalR Core using ChannelWriter: Do I need to call TryComplete twice if there's an exception?
以下是 Microsoft Use streaming in ASP.NET Core SignalR 文章的摘录:
private async Task WriteItemsAsync(
ChannelWriter<int> writer,
int count,
int delay,
CancellationToken cancellationToken)
{
try
{
for (var i = 0; i < count; i++)
{
// Check the cancellation token regularly so that the server will stop
// producing items if the client disconnects.
cancellationToken.ThrowIfCancellationRequested();
await writer.WriteAsync(i);
// Use the cancellationToken in other APIs that accept cancellation
// tokens so the cancellation can flow down to them.
await Task.Delay(delay, cancellationToken);
}
}
catch (Exception ex)
{
writer.TryComplete(ex);
}
writer.TryComplete();
}
如果有异常,会先调用writer.TryComplete(ex),然后调用writer.TryComplete()。换句话说,它两次调用 TryComplete(尽管重载不同)。
有这个必要吗?我应该在 writer.TryComplete(ex) 之后添加一个 return 语句以避免调用它两次吗?还是第二个 writer.TryComplete() 在调用前一个之后起到了一些有意义的作用?
没必要。这不是频道制作人的最佳例子。 writer.TryComplete()
应该是 try{}
块的最后一次调用:
private async Task WriteItemsAsync(
ChannelWriter<int> writer,
int count,
int delay,
CancellationToken cancellationToken)
{
try
{
for (var i = 0; i < count; i++)
{
// Check the cancellation token regularly so that the server will stop
// producing items if the client disconnects.
cancellationToken.ThrowIfCancellationRequested();
await writer.WriteAsync(i);
// Use the cancellationToken in other APIs that accept cancellation
// tokens so the cancellation can flow down to them.
await Task.Delay(delay, cancellationToken);
}
writer.TryComplete();
}
catch (Exception ex)
{
writer.TryComplete(ex);
}
}
这样,它只被调用一次,无论是在循环成功终止时,还是在由于任何原因抛出异常时。
您可以简单地跳出循环,而不是使用 ThrowIfCancellationRequested
取消取消:
for (var i = 0; i < count; i++)
{
if (cancellationToken.IsCancellationRequested)
{
break;
}
await writer.WriteAsync(i);
await Task.Delay(delay, cancellationToken);
}
writer.TryComplete();
在有界频道的情况下,WriteAsync
也应该收到取消令牌,否则如果频道已满可能会卡住:
await writer.WriteAsync(i,cancellationToken);
以下是 Microsoft Use streaming in ASP.NET Core SignalR 文章的摘录:
private async Task WriteItemsAsync(
ChannelWriter<int> writer,
int count,
int delay,
CancellationToken cancellationToken)
{
try
{
for (var i = 0; i < count; i++)
{
// Check the cancellation token regularly so that the server will stop
// producing items if the client disconnects.
cancellationToken.ThrowIfCancellationRequested();
await writer.WriteAsync(i);
// Use the cancellationToken in other APIs that accept cancellation
// tokens so the cancellation can flow down to them.
await Task.Delay(delay, cancellationToken);
}
}
catch (Exception ex)
{
writer.TryComplete(ex);
}
writer.TryComplete();
}
如果有异常,会先调用writer.TryComplete(ex),然后调用writer.TryComplete()。换句话说,它两次调用 TryComplete(尽管重载不同)。
有这个必要吗?我应该在 writer.TryComplete(ex) 之后添加一个 return 语句以避免调用它两次吗?还是第二个 writer.TryComplete() 在调用前一个之后起到了一些有意义的作用?
没必要。这不是频道制作人的最佳例子。 writer.TryComplete()
应该是 try{}
块的最后一次调用:
private async Task WriteItemsAsync(
ChannelWriter<int> writer,
int count,
int delay,
CancellationToken cancellationToken)
{
try
{
for (var i = 0; i < count; i++)
{
// Check the cancellation token regularly so that the server will stop
// producing items if the client disconnects.
cancellationToken.ThrowIfCancellationRequested();
await writer.WriteAsync(i);
// Use the cancellationToken in other APIs that accept cancellation
// tokens so the cancellation can flow down to them.
await Task.Delay(delay, cancellationToken);
}
writer.TryComplete();
}
catch (Exception ex)
{
writer.TryComplete(ex);
}
}
这样,它只被调用一次,无论是在循环成功终止时,还是在由于任何原因抛出异常时。
您可以简单地跳出循环,而不是使用 ThrowIfCancellationRequested
取消取消:
for (var i = 0; i < count; i++)
{
if (cancellationToken.IsCancellationRequested)
{
break;
}
await writer.WriteAsync(i);
await Task.Delay(delay, cancellationToken);
}
writer.TryComplete();
在有界频道的情况下,WriteAsync
也应该收到取消令牌,否则如果频道已满可能会卡住:
await writer.WriteAsync(i,cancellationToken);