如何避免每个消耗大量内存的异步方法出现OutOfMemoryException?

时间:2017-01-24 16:47:31

标签: c# asynchronous memory async-await out-of-memory

我正在尝试处理一些在阅读时显着扩展的项目列表。我在异步函数中处理它们,所以可能会发生在某些时候运行太多函数并抛出OutOfMemoryException。

我正在考虑根据某些硬限制来限制正在运行但未完成的同时任务的数量。但我无法预测有多少任务太少/太多,因为每个项目可能会有不同的扩展。

在没有引入硬限制的情况下,是否有一些聪明的方法可以避免异常?

引发行为的示例:

void Main()
{        
    Int32 million = 1000000;    
    List<Task> tasks = new List<Task>();
    for (Int32 i = 0; i < 20; i++)
    {
        Task t = Do(million);
        tasks.Add(t);
    }   
    Task.WaitAll(tasks.ToArray());
}


public static async Task Do(Int32 count)
{
    //I tried 'await Task.Yield()' here; didn't help.

    //consume memory
    StringBuilder dataBuilder = new StringBuilder();
    for (Int32 i = 0; i < count; i++)
    {
        dataBuilder.Append(Guid.NewGuid().ToString());
    }
    String data = dataBuilder.ToString();
    Console.WriteLine($"here [{data.Length}]");
    //do I/O
    await Task.Delay(10000);
}

1 个答案:

答案 0 :(得分:0)

使用流式样式代替巨型缓冲区样式代码。

public static async Task Do(Int32 count)
{
    //I tried 'await Task.Yield()' here; didn't help.

    //consume memory
    for (Int32 i = 0; i < count; i++)
    {
        Console.Write(Guid.NewGuid().ToString());
    }

    //do I/O
    await Task.Delay(10000);
}

我们的想法是不缓冲所有输出并在最后发送它,而是在创建时将其发送到文件,网络,帧缓冲区等等。