当发生异常时,如何取消iAsyncencentoser?

发布于 2025-02-06 16:46:06 字数 817 浏览 2 评论 0原文

我正在使用iasyncenumerable来获取大量数据 - 像这样:

static async IAsyncEnumerable<int> GetSequence([EnumeratorCancellation] CancellationToken ct = default)
{
    for (int i = 1; i <= 10; i++)
    {
        var data = await DoSomethingAsync()    // get data from web request
        yield return data;
    }
}

现在是我的问题:如果dosomethingsasync thr thr thr tragriation(也许是网络问题),我想取消剩余的请求,有可能吗?

我正在尝试以下代码来处理,但仍然需要帮助:

CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;

try
{
    IAsyncEnumerable<int> dataCol = GetSequence(token);

    await foreach (var d in dataCol)
    {
        // do ...
    }
}
catch (Exception)
{
   source.Cancel(true);
   throw;
}

感谢某人有最佳实践

I am using IAsyncEnumerable to fetch a lot of data - like this:

static async IAsyncEnumerable<int> GetSequence([EnumeratorCancellation] CancellationToken ct = default)
{
    for (int i = 1; i <= 10; i++)
    {
        var data = await DoSomethingAsync()    // get data from web request
        yield return data;
    }
}

Now here is my question: if DoSomethingAsync throws an exception (maybe a network issue), I would like to cancel the remaining requests, is it possible?

I am trying below code to handle but still need help:

CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;

try
{
    IAsyncEnumerable<int> dataCol = GetSequence(token);

    await foreach (var d in dataCol)
    {
        // do ...
    }
}
catch (Exception)
{
   source.Cancel(true);
   throw;
}

Appreciate if someone has best practices

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

猫瑾少女 2025-02-13 16:46:06

来自原始

await foreach (var d in dataCol)
{
    // do ...
}

等同于;

{
    E e = dataCol.GetAsyncEnumerator();
    try {
        while (await e.MoveNextAsync()) {
            var d = e.Current;
            // do ...
        }
    }
    finally {
        ... // Dispose e
    }
}

调用movenextAsync导致您的get sequence方法执行到下一个收益率返回,或者直到抛出未手动的异常为止。执行该方法不会恢复,直到下一个呼叫moveNextAsyncget sequence等待着foreach不同行运行,他们轮流执行更多的代码在同步的任务中。

如果Dosomethingsasync抛出异常

,则等待e.movenextasync()将重新添加异常。然后将处置枚举者。然后,异常将堆栈流到下一个异常处理程序。

您无需弄乱取消令牌即可防止获取序列恢复执行。实际上,从中分解出循环也将中止执行,好像收益率返回从未恢复过。在get sequence方法中,导致任何终于{}块执行,如果有的话。

From the original language proposal

await foreach (var d in dataCol)
{
    // do ...
}

is equivalent to;

{
    E e = dataCol.GetAsyncEnumerator();
    try {
        while (await e.MoveNextAsync()) {
            var d = e.Current;
            // do ...
        }
    }
    finally {
        ... // Dispose e
    }
}

Calling MoveNextAsync causes your GetSequence method to execute up to the next yield return, or until an unhandled exception is thrown. Execution of that method will not resume until the next call to MoveNextAsync. GetSequence and await foreach do not run in parallel, they take turns executing more code within the same async task.

if DoSomethingAsync throws an exception

then await e.MoveNextAsync() will re-throw the exception. Then enumerator will be disposed. Then the exception would flow up the stack to the next exception handler.

You don't need to mess around with cancelation tokens to prevent GetSequence from resuming execution. In fact breaking out of the await foreach loop would also abort execution, as if the yield return never resumed. Causing any finally{} blocks in your GetSequence method to execute, if you had any.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文