1

我正在使用 ConcurrentQueue (C#, ASP.NET Core) 来保存上传大文件的任务。即使在项目从并发队列中出列之后,我的内存消耗也非常大。项目不会从内存中清除。

我了解 ASP.NET Core 中 ConcurrentQueue 的行为,简而言之:并发队列中的 32 个项目的每一组都保存在一个单独的段中。仅在特定段中的所有项目都出列后,而不是在为单个项目调用 TryDequeue() 方法之后,才释放出列项目的引用。在我的情况下这是一个问题,因为如果在最坏的情况下没有清理 32 个项目(可能是非常大的 zip 文件),我的内存中可能会有非常大的数量。我什至不希望队列中同时有超过 32 个项目。

即使我提取文件并单独发送它们,里面的每个文件/图像本身也可以很大。唯一对我来说足够好的事情是释放每个出队项目的参考,而无需进一步推迟。有可能吗?怎么做?

我尝试使用 StrongBox,在一些文章中推荐:

ConcurrentQueue<StrongBox<Func<CancellationToken, Task>>> 
workItems = new ConcurrentQueue<StrongBox<Func<CancellationToken, Task>>>();

// Enqueuing:
this.workItems.Enqueue(new StrongBox<Func<CancellationToken, Task>>(workItem));

// Dequeuing:
workItems.TryDequeue(out var workItem);
return workItem.Value;

这对我来说没有用。内存没有被释放。我不知道我的问题与我正在向队列发送对函数的引用并且它以某种方式保存在内存中的事实有关。该函数的参数之一是上传的具体文件。其他的只是字符串。

最后,我想在调用 TryDequeue() 方法之后或期间处理该项目的内存释放。有可能吗?怎么做?

4

2 回答 2

1

请参阅此处接受的答案的评论:ConcurrentQueue<StrongBox<T>> 的使用

这个想法是您可以ValueStrongBox. 所以你的代码变成:

// Dequeuing:
workItems.TryDequeue(out var workItem);
var returnValue = workItem.Value;
workItem.Value = null; // see below
return returnValue;

通过设置workItem.Value = null,您将删除该StrongBox项目的引用。因此,一旦您的代码完成使用它,就不再有对该项目的引用,并且可以收集它。当然,队列继续持有对 的引用StrongBox,但那东西很小。

于 2019-01-30T22:44:49.113 回答
0

我处理使用 Try..Catch.. finally模式。使用最终模式将变量设置为 null 是要走的路。处理点在finally部分返回,您可以在那里释放未使用的资源。我构建了交易软件,它必须干净且无内存泄漏!!!!祝你好运!

static public ionDESK.Response.GenericResponse<object> RunScript(StrategyInput e)
    {

        var r = new ionDESK.Response.GenericResponse<object>();
        try
        {
            r = e.ExecuteStrategy();
            return r;
        }
        catch (Exception ex)
        {
            r.Errors.Add(ex.Message + " ExecuteStrategy " + ex.StackTrace);
            return r;
        }
        finally
        {
            // When it returns...free resource
            r = null;
        }
    }
于 2020-06-20T18:32:59.303 回答