C# 使用就绪堆栈的多线程处理

C# 使用就绪堆栈的多线程处理,c#,multithreading,stack,locking,monitor,C#,Multithreading,Stack,Locking,Monitor,我有一个导致性能问题的问题。我有一个地图应用程序,一些分幅是动态生成的,另一些是缓存和重试的。这两种方法都使用多线程。问题是,如果动态生成tile,并且有大量数据需要检索,那么就会出现性能问题。用户平移/缩放,应用程序必须查询信封中的所有内容,并在每次地图更改时返回图像。如果我锁定了动态生成平铺的方法,那么缓存的文件会快速生成,但动态平铺的生成需要很长时间,尤其是当用户进行大量平移和缩放时。我的问题是: 有没有办法实现一个锁,然后在方法完成后,访问就绪队列中的最后一个线程?我想我要找的是一个现成

我有一个导致性能问题的问题。我有一个地图应用程序,一些分幅是动态生成的,另一些是缓存和重试的。这两种方法都使用多线程。问题是,如果动态生成tile,并且有大量数据需要检索,那么就会出现性能问题。用户平移/缩放,应用程序必须查询信封中的所有内容,并在每次地图更改时返回图像。如果我锁定了动态生成平铺的方法,那么缓存的文件会快速生成,但动态平铺的生成需要很长时间,尤其是当用户进行大量平移和缩放时。我的问题是:

有没有办法实现一个锁,然后在方法完成后,访问就绪队列中的最后一个线程?我想我要找的是一个现成的堆栈,而不是一个现成的队列。这样,用户当前所在的区域将更快地生成其磁贴


我正在使用本地Web服务生成互动程序。到目前为止,我已经做到了这一点。

您根本不需要使用任何锁定,只需使用线程安全的堆栈实现,就像保留要执行的工作队列一样。然后,您只需要让您的工作线程池分别从这个堆栈中推送和/或拉取要执行的工作

使用
Parallel.ForEach
和阻塞集合,您可以非常轻松地使用.NET4.5实现整个工作队列系统。你没有提供代码,所以我不得不为一个例子做一些补充,但它可以像这样工作

public void StartTileProcessor()
{
    //The default for a BlockingCollection is a Queue, but you can pass in a stack for the underlying collection and it will behave as a stack.
    var stack = new BlockingCollection<UnprocessedTileMetadata>(new ConcurrentStack<UnprocessedTileMetadata>());

    var processorThread = Task.Run(() => ProcessTiles(stack));

    _yourGui.TileRequested += (sender, e) => stack.Add(e.RequestedTile);

    //...
}

/// <summary>
/// The method for processing tiles, takes from the stack and returns to the output.
/// </summary>
/// <param name="inputStack">The blocking collection that represents the input stack.</param>
private void ProcessTiles(BlockingCollection<UnprocessedTileMetadata> inputStack)
{
    //This is done so the foreach does not try to buffer requests from the consuming enumerable, the next item it processes will be the last added to the stack.
    var partitioner = Partitioner.Create(inputStack.GetConsumingEnumerable(), EnumerablePartitionerOptions.NoBuffering);
    Parallel.ForEach(partitioner, (unprocessedTile) =>
    {
        ProcessedTile tile = GenerateOrGetFromCache(unprocessedTile);
        _yourGui.SendToDisplay(tile);
    });
}
public void StartTileProcessor()
{
//BlockingCollection的默认值是队列,但您可以为基础集合传入堆栈,它将作为堆栈。
var stack=new BlockingCollection(new ConcurrentStack());
var processorhread=Task.Run(()=>ProcessTiles(堆栈));
_yourGui.TileRequested+=(发送方,e)=>stack.Add(e.requestedfile);
//...
}
/// 
///处理平铺的方法,从堆栈中提取并返回到输出。
/// 
///表示输入堆栈的阻塞集合。
私有void ProcessTiles(BlockingCollection输入堆栈)
{
//这样,foreach就不会试图缓冲来自消费枚举的请求,它处理的下一项将是最后添加到堆栈的项。
var partitioner=partitioner.Create(inputStack.getconsumineGenumerable(),EnumerablePartitionOptions.NoBuffering);
Parallel.ForEach(分区器,(未处理文件)=>
{
ProcessedFile磁贴=GenerateTargetFromCache(未处理的文件);
_yourGui.SendToDisplay(tile);
});
}

到目前为止,您得到了什么?很抱歉,我一开始没有包含代码。很抱歉,我应该说得更清楚。我正在使用本地Web服务生成互动程序。以下是我到目前为止所做的。不要在注释中添加代码。更新你的问题,说明你做了什么。