我可以取消StreamReader.ReadLineAsync用的CancellationToken? [英] Can i cancel StreamReader.ReadLineAsync with a CancellationToken?

查看:389
本文介绍了我可以取消StreamReader.ReadLineAsync用的CancellationToken?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我通过调用取消我的异步方法有以下内容取消()的方法,我的 CancellationTokenSource ,它最终会停止。因为该行然而 Console.WriteLine(等待reader.ReadLineAsync()); 需要相当长来完成,我想我的CancellationToken传递给 ReadLineAsync ()以及(希望它返回一个空字符串),以使该方法更适应我的取消()电话。但是我不能错过一个的CancellationToken ReadLineAsync()

When I cancel my async method with the following content by calling the Cancel() method of my CancellationTokenSource, it will stop eventually. However since the line Console.WriteLine(await reader.ReadLineAsync()); takes quite a bit to complete, I tried to pass my CancellationToken to ReadLineAsync() as well (expecting it to return an empty string) in order to make the method more responsive to my Cancel() call. However I could not pass a CancellationToken to ReadLineAsync().

我可以取消调用Console.WriteLine() Streamreader.ReadLineAsync(),如果是这样,我该怎么办呢?

Can I cancel a call to Console.WriteLine() or Streamreader.ReadLineAsync() and if so, how do I do it?

为什么 ReadLineAsync()不接受的CancellationToken ?我认为这是很好的做法给予异步方法,即使该方法被取消后,仍然完成了一个可选的的CancellationToken 参数。

Why is ReadLineAsync() not accepting a CancellationToken? I thought it was good practice to give Async methods an optional CancellationToken parameter even if the method still completes after being canceled.

StreamReader reader = new StreamReader(dataStream);
while (!reader.EndOfStream)
{
    if (ct.IsCancellationRequested){
        ct.ThrowIfCancellationRequested();
        break;
    }
    else
    {
        Console.WriteLine(await reader.ReadLineAsync());
    }
}

更新
就像在下面的评论指出的那样, Console.WriteLine()单独调用已经被占用了,由于每行40.000字符格式化不佳输入字符串几秒钟。打破下来解决了我的响应时间问题,但我仍然有兴趣在如何取消这场旷日持久的声明有任​​何建议或解决方法,如果由于某种原因写入40.000字符转换成一条线的目的(例如倾销整个字符串转换成时文件)。

Update Like stated in the comments below, the Console.WriteLine() call alone was already taking up several seconds due to a poorly formated input string of 40.000 characters per line. Breaking this down solves my response-time issues, but I am still interested in any suggestions or workarounds on how to cancel this long-running statement if for some reason writing 40.000 characters into one line was intended (for example when dumping the whole string into a file).

推荐答案

您无法取消操作,除非它是撤销。您可以使用 WithCancellation 扩展方法让你的code流量的行为,如果它被取消了,但潜在仍将运行:

You can't cancel the operation unless it's cancellable. You can use the WithCancellation extension method to have your code flow behave as if it was cancelled, but the underlying would still run:

public static Task<T> WithCancellation<T>(this Task<T> task, CancellationToken cancellationToken)
{
    return task.IsCompleted // fast-path optimization
        ? task
        : task.ContinueWith(
            completedTask => completedTask.GetAwaiter().GetResult(),
            cancellationToken,
            TaskContinuationOptions.ExecuteSynchronously,
            TaskScheduler.Default);
}

用法:

await task.WithCancellation(cancellationToken);

您不能取消 Console.WriteLine ,你不需要。它的瞬间,如果你有一个合理的大小字符串

You can't cancel Console.WriteLine and you don't need to. It's instantaneous if you have a reasonable sized string.

关于指导:如果您的实现实际上并不支持取消你不应该接受一个令牌,因为它发出了一个混合的信息。

About the guideline: If your implementation doesn't actually support cancellation you shouldn't be accepting a token since it sends a mixed message.

如果你有一个巨大的字符串写信给你不应该使用 Console.WriteLine 控制台。可以在一个时间写在字符的串和具有该方法是撤销:

If you do have a huge string to write to the console you shouldn't use Console.WriteLine. You can write the string in a character at a time and have that method be cancellable:

public void DumpHugeString(string line, CancellationToken token)
{
    foreach (var character in line)
    {
        token.ThrowIfCancellationRequested();
        Console.Write(character);
    }

    Console.WriteLine();
}

一个更好的解决办法是分批的,而不是单个字符来写。下面是使用实施 MoreLinq 批量

public void DumpHugeString(string line, CancellationToken token)
{
    foreach (var characterBatch in line.Batch(100))
    {
        token.ThrowIfCancellationRequested();
        Console.Write(characterBatch.ToArray());
    }

    Console.WriteLine();
}

所以,结论是:

var reader = new StreamReader(dataStream);
while (!reader.EndOfStream)
{
    DumpHugeString(await reader.ReadLineAsync().WithCancellation(token), token);
}

这篇关于我可以取消StreamReader.ReadLineAsync用的CancellationToken?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆