gpt4 book ai didi

c# - BlockingCollection + UI 线程

转载 作者:行者123 更新时间:2023-11-30 16:32:32 24 4
gpt4 key购买 nike

我关注了this tutorial , 创建一个优先级队列并用阻塞集合包装它。我有一个 DataGrid,我已将其连接到发出更改事件的底层优先级队列。我可以从 UI 线程向集合中添加项目而不会出现故障,并且当缓冲区已满时它会按预期阻塞。

现在我该如何消费这些元素?这是我得到的:

public DownloadViewModel()
{
Queue = new ConcurrentPriorityQueue<DownloadItem>(10);
Buffer = new BlockingCollection<KeyValuePair<int, DownloadItem>>(Queue, 10000);

Task.Factory.StartNew(() =>
{
KeyValuePair<int, DownloadItem> item;
while(!Buffer.IsCompleted)
{
if(Buffer.TryTake(out item))
{
// do something with the item
}

Thread.SpinWait(100000);
}
});
}

但是一旦我添加了 Task.Factory.StartNew 位,我的应用程序突然需要 30 秒才会出现窗口(在它是即时的之前),当我添加一个项目时我得到异常

This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.

我明白了,但是真的有必要使用 UI 线程来获取项目吗?这不会破坏使用此 BlockingCollection 的全部目的吗?我想创建 4 或 8 个消费者并让它们并行运行。

这应该如何完成?

最佳答案

用调度程序包装 CollectionChanged 事件似乎工作得很好......

public bool TryAdd(KeyValuePair<int, T> item)
{
int pos = _queues.Take(item.Key + 1).Sum(q => q.Count);
_queues[item.Key].Enqueue(item.Value);
Interlocked.Increment(ref _count);
Dispatcher.BeginInvoke(
new Action(
() =>
NotifyCollectionChanged(
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, pos))
));
return true;
}

只需从 DispatcherObject 派生出我的 ConcurrentPriorityQueue。我认为应该这样做。


更简单,只需像这样编写 NotifyCollectionChanged 方法:

private void NotifyCollectionChanged(NotifyCollectionChangedEventArgs e)
{
lock (CollectionChanged)
{
if (CollectionChanged != null)
Dispatcher.BeginInvoke(new Action(() => CollectionChanged(this, e)));
}
}

然后您就不必用 BeginInvoke 乱丢其他方法了。

关于c# - BlockingCollection + UI 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3972273/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com