c# - 随后将任务添加到任务中,但限制并行执行的数量
问题描述
当我想在包含超过 10k 个条目的网格中显示缩略图时,我遇到了严重的性能问题,即 100% 运行四个内核,阻塞了其他所有内容。
当向用户显示一行时会触发一个事件,该事件会加载图像。在这种情况下,GridImageManager
使用 调用的实例AddAndStartLoading
。当我向下滚动时,这个事件被触发得太频繁了,我的核心被线程淹没了。
我试图重写代码,使用回调和仍然加载单元的列表,但该列表不是线程安全的,导致异常,当我想删除一个已经从另一个线程中删除的元素时。
然后我尝试使用信号量,但使用它们我无法实现WaitForLoadingCompleted
- 方法,因为我无法访问大量空闲资源。
我也阅读了 Tasks,但不知道它们将如何帮助我。
我的限制如下:
- 加载图像必须在第一次调用之后立即开始
AddAndStartLoading
。 - 任何
N
时候都不应执行加载过程。 - 后续调用
AddAndStartLoading
可能会等待,但应在加载过程量降至N
. WaitForLoadingCompleted
应该等待所有 Loading 线程完成,而另一方面允许做Application.DoEvents()
. 我目前无法重构它。
我必须使用哪些模式/策略来完成此任务?
给你一个想法:这是我的第一次尝试。CellsToLoad
它可以工作到变空的地步。
public class GridImageManager
{
public GridImageManager()
{
CellsToLoad = new List<(UltraGridCell cell, ImageLoader loader)>();
LoadingCells = new Dictionary<UltraGridCell, ImageLoader>();
}
public delegate void ImageLoader(object obj);
private List<(UltraGridCell cell, ImageLoader loader)> CellsToLoad { get; set; }
private Dictionary<UltraGridCell, ImageLoader> LoadingCells { get; set; }
public void AddCellToLoad(UltraGridCell cell, ImageLoader loader)
{
CellsToLoad.Add((cell, loader));
StartLoading();
}
private void CallbackImageLoaded(IAsyncResult ar)
{
if (ar.AsyncState is UltraGridCell cell)
{
LoadingCells.Remove(cell);
StartLoading();
}
}
private void StartLoading()
{
if (LoadingCells.Count >= 10)
return;
if (CellsToLoad.Count == 0)
return;
var next = CellsToLoad.First();
CellsToLoad.Remove(next);
LoadingCells.Add(next.cell, next.loader);
next.loader.BeginInvoke(null, CallbackImageLoaded, next.cell);
}
public void WaitForLoadingCompleted()
{
while (CellsToLoad.Count > 0 && LoadingCells.Count > 0)
{
Application.DoEvents(); // Can't refactor this right now
}
}
}
解决方案
推荐阅读
- php - 表 php 中的 if 语句
- metal - Metal如何将图像块分配给每个线程组?
- android - android 应用程序打开时,如何编写运行 JavaScript 的 html 文件?
- wordpress - CSS @page 不适用
- c# - 有没有办法通过 javascript 的 httpwebrequest 获取实时数据?
- javascript - 单击另一个按钮时如何在按钮上创建幻灯片效果
- java - 针对特定领域的 MVC 上的观察者模式
- java - 是否可以挂钩生命周期事件,类似于 Autofac 的 OnActivating 或 OnActivated
- ruby-on-rails - 如何在 ruby on rails 中正确显示数据库中的图像
- button - 单击时临时更改按钮的颜色