小编Mon*_*mas的帖子

如何避免此async/await程序中可能的堆栈溢出?

下面是一个在使用该方法时可能出现堆栈溢出的程序示例DependsOnPreviousTaskAsync,这是令人惊讶的,因为我不相信有任何显式的同步递归.

在编码到方法中的断点处发生溢出之前,您可以看到堆栈的示例DoSomething.将有一大堆潜在的异步状态机调用.

由于任务与其前任之间存在依赖关系,因此存在逻辑链,但我很惊讶这串异步调用在调用堆栈上递归显示!

为了解决这个问题,我将方法编码为DependsOnPreviousTaskAsync2,使用旧式ContinueWith连续处理而不是async/await.在这种情况下,在断点处观察到的调用堆栈永远不会很深.

我的问题是,是否有一些关于使用async/await的问题,这会阻止堆栈溢出?或者我是否只是遇到了需要使用变通方法打破async/await状态机固有的惊人递归的边缘情况?

编辑:我已添加TaskContinuationOptions.ExecuteSynchronously到变通方法版本,虽然观察到的调用堆栈可能更深,但我没有看到使用此方法的任何StackOverflowExceptions.无论堆栈溢出检测逻辑被成功地被施加到ContinueWith并且ExecuteSynchronous在异步/ AWAIT版本被施加.

class Program
{
    public async static Task<int> DependsOnPreviousTaskAsync(Task<int> previousTask)
    {
        if (previousTask == null)
            return 0;

        var result = await DoSomethingAsync(previousTask).ConfigureAwait(false);
        Console.WriteLine(result);
        return result;
    }

    public static Task<int> DependsOnPreviousTaskAsync2(Task<int> previousTask)
    {
        // this is a non async/await version of DependsOnPreviousTaskAsync

        if (previousTask == null)
            return Task.FromResult(0);

        var tcs = new TaskCompletionSource<int>();

        DoSomethingAsync(previousTask)
            .ContinueWith(t =>
            {
                if …
Run Code Online (Sandbox Code Playgroud)

c# multithreading async-await

6
推荐指数
1
解决办法
1760
查看次数

标签 统计

async-await ×1

c# ×1

multithreading ×1