使用 Task.Run() 时如何避免 OutOfMemoryException? [复制]

Posted

技术标签:

【中文标题】使用 Task.Run() 时如何避免 OutOfMemoryException? [复制]【英文标题】:How to avoid OutOfMemoryException when using Task.Run()? [duplicate] 【发布时间】:2020-12-28 10:58:46 【问题描述】:

当我在启动时调用此方法时出现 OutOfMemoryException。 StartSignalR 方法应该运行一个每秒调用 Update() 方法的任务。

  public void StartSignalR()

    

        Task t = Task.Run(() =>
        
            try
            
                bool push = true;
                while (push)
                
                    Update();
                
            
            catch (System.Exception ex)
            
                LogManager.LogError(ex);
            
        );
    

我在 Update() 中使用 Task.Delay

 private async static void Update()
    
        await Task.Delay(1000);
        
        Updater.MPrice();
    

【问题讨论】:

Task.Run 肯定不会导致 OOM 异常。你需要查看和调试你的代码,你在某处有内存泄漏 @CamiloTerevinto 如果我不调用此方法,则不会发生 OOM 您可能每秒调用Update() 数百万次,因此Updater.MPrice() 中的任何内容都会在某处泄漏内存,或者创建足够大的对象以使您的系统内存不足。您需要await 拨打Update 请分享minimal reproducible example,包括MPrice的源代码。 另外,您忘记在Update 上调用awaitUpdate 应该返回Task 而不是void 【参考方案1】:

要让您的 Task.Delay 真正等待,您必须将您的 lambda 声明为 asyncawait Update 方法。

public void StartSignalR()

    //added async
    Task t = Task.Run(async () =>
    
        try
        
            bool push = true;
            while (push)
            
                //await the Update method
                await Update();
            
        
        catch (System.Exception ex)
        
            LogManager.LogError(ex);
        
    );

通过此更改,您的 Update 方法必须返回 Task

//changed signature
private async static Task Update()

这很有可能会减少内存占用,因为目前您正在疯狂地触发 Update 方法。

【讨论】:

以上是关于使用 Task.Run() 时如何避免 OutOfMemoryException? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

C#使用异步操作时的注意要点(翻译)

避免 Task.Run 导致主线程死锁(C#)

Task.Run使用默认线程池

使用 Task.Run() 时如何限制最大线程数?

如何停止 Task.Run()?

在 Task.Run() 中包装同步调用以使其异步有益吗?