随后将任务添加到任务,但限制并行执行任务的数量

时间:2018-10-25 12:28:46

标签: c# multithreading winforms async-await

我遇到严重的性能问题,即当我想在包含超过1万个条目的网格中显示缩略图时,四个内核以100%的速度运行,从而阻塞了其他所有内容。
当向用户显示一条线时会触发一个事件,该事件会加载图像。在这种情况下,GridImageManager的实例将被AddAndStartLoading调用。当我向下滚动时,此事件触发得太多,并且我的核心被线程淹没。

我尝试使用回调和仍然要加载的单元的列表来重写代码,但是该列表不是线程安全的,导致异常,当我想删除一个已经从另一个线程中删除的元素时。 / p>

然后,我尝试使用信号量,但是有了它们,我无法实现WaitForLoadingCompleted方法,因为我无法访问大量的可用资源。

我也读过Tasks,但无法了解它们如何帮助我。

我的约束如下:

  • 在第一次调用AddAndStartLoading之后,必须立即开始加载图像。
  • 任何时候最多只能执行N个加载过程。
  • 随后对AddAndStartLoading的调用可能会等待,但是一旦加载进程的数量降到N以下,就应该处理。
  • WaitForLoadingCompleted应该等待所有的加载线程完成,而另一方面允许执行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
        }
    }
}

0 个答案:

没有答案