如何从ConcurrentQueue中释放对使用TryDequeue从并发队列中退出的项目的引用



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

我理解ASP.NET Core中并发队列的行为,简而言之:并发队列中的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()方法之后或期间处理该项的内存释放。这可能吗?怎么可能?

请参阅此处对已接受答案的评论:ConcurrentQueue<StrongBox<T>gt;。

其思想是,可以使StrongBoxValue属性为空。所以你的代码变成:

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

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

我使用Try。。捕获最后模式。使用最后的模式将变量设置为null是可行的。处理点最终返回部分,您可以在那里释放未使用的资源。我建立交易软件,它必须是干净的,内存泄漏免费!!!!祝你好运

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;
}
}

最新更新