C# OperationCanceledException之后,永远不会完成ChannelReader完成任务

C# OperationCanceledException之后,永远不会完成ChannelReader完成任务,c#,.net,system.threading.channels,C#,.net,System.threading.channels,如果调用Stop(),则会发生操作取消异常,并且\u writer.TryComplete(exp)为true。但是\u阅读器。完成任务任务仍未完成 这是渠道的预期行为吗?如果是,是否有人能告诉我如何停止频道,而不必等到频道为空并使其完成任务处于完成状态 公共接口项目 { Uri SourceUri{get;} 字符串TargetPath{get;} } 公共类项目:IItem { 公共项(Uri sourceUri,字符串targetPath) { SourceUri=SourceUri; T

如果调用
Stop()
,则会发生
操作取消异常
,并且
\u writer.TryComplete(exp)
为true。但是
\u阅读器。完成任务
任务
仍未完成

这是渠道的预期行为吗?如果是,是否有人能告诉我如何停止
频道
,而不必等到频道为空并使其
完成
任务处于
完成
状态

公共接口项目
{
Uri SourceUri{get;}
字符串TargetPath{get;}
}
公共类项目:IItem
{
公共项(Uri sourceUri,字符串targetPath)
{
SourceUri=SourceUri;
TargetPath=TargetPath;
}
公共Uri源Uri{get;}
公共字符串TargetPath{get;}
}
公共类测试服务
{
专用只读通道编写器(ChannelWriter);;
专用只读通道读卡器(U读卡器);
私有只读取消令牌源;
公共测试服务()
{
_cts=新的CancellationTokenSource();
Channel=Channel.CreateUnbounded();
_读卡器=通道读卡器;
_writer=channel.writer;
}
公共异步任务队列下载(项目信息)
{
wait_writer.WriteAsync(信息);
}
public void StartDownload()
{
Task.Factory.StartNew(异步()=>
{
等待ProcessDownloadAsync();
},TaskCreationOptions.LongRunning);
}
公共停车场()
{
_cts.Cancel();
//_writer.Complete();
//_writer=null;
控制台。写入线(“停止”);
}
公共异步任务等待()
{
等待读者完成;
}
专用异步任务ProcessDownloadAsync()
{
尝试
{
while(wait _reader.WaitToReadAsync(_cts.Token))
{
IItem信息=等待_reader.ReadAsync(_cts.Token);
使用(WebClient WebClient=new WebClient())
{
Console.WriteLine(information.TargetPath);
等待webClient.DownloadFileTaskAsync(information.SourceUri,
信息。目标路径);
}
}
}
捕获(操作取消异常扩展)
{
bool res=\u writer.TryComplete(exp);
}
}
}
静态类程序
{
静态异步任务主(字符串[]args)
{
TestService tSvc=新的TestService();
等待tSvc.QueueDownload(新项目(新Uri)(@)https://images.pexels.com/" +
@“photos/753626/pexels-photo-753626.jpeg”),@“D:\\Temp\1.png”);
等待tSvc.QueueDownload(新项目(新Uri)(@)https://images.pexels.com/" +
@“photos/753626/pexels-photo-753626.jpeg”),@“D:\\Temp\1.png”);
等待tSvc.QueueDownload(新项目(新Uri)(@)https://images.pexels.com/" +
@“photos/753626/pexels-photo-753626.jpeg”),@“D:\\Temp\1.png”);
等待tSvc.QueueDownload(新项目(新Uri)(@)https://images.pexels.com/" +
@“photos/753626/pexels-photo-753626.jpeg”),@“D:\\Temp\1.png”);
tSvc.StartDownload();
Task t=tSvc.Wait();
tSvc.Stop();
等待t;
控制台。写入线(“完成”);
}
}
该方法的行为与预期略有不同。它不会立即使频道的内容无效。相反,它只是阻止在频道中添加更多项目。现有项目仍然可以使用,并且在使用所有存储的项目之前,属性将不会完成

下面的示例演示了此行为:

var channel = Channel.CreateUnbounded<int>();
channel.Writer.TryWrite(1);
channel.Writer.Complete(new FileNotFoundException());
//channel.Reader.TryRead(out var data);
var completed = channel.Reader.Completion.Wait(500);
Console.WriteLine($"Completion: {(completed ? "OK" : "Timed-out")}");

您可以取消注释
channel.Reader.TryRead
行,以查看出现的
FileNotFoundException

感谢您的解释和示例。主要问题是:在这种情况下,是否有可能以某种方式清除频道的内容以启动Complition?@d.lavysh我想您可以手动执行,使用如下循环:
while(_reader.TryRead(out))){}
这对于频道来说是正常的。如果您想要“丢弃刷新”,那么您需要(也可以选择取消消费者),或者使用TPL数据流并调用
IDataflowBlock.Fault
丢弃输入。