Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从线程池向ObservableCollection添加项_C#_Multithreading - Fatal编程技术网

C# 从线程池向ObservableCollection添加项

C# 从线程池向ObservableCollection添加项,c#,multithreading,C#,Multithreading,我的问题很简单,我有一个类,它包含一个类型为observedcollection的(私有)对象,现在我想运行一些线程(按顺序,因此是ThreadPool而不是BackgroundWorkers),它们向observedcollection添加新项 如果observedcollection将是一个ProgressBar,那么一切都将非常简单(->调用),但我不知道如何调用observedcollection对象 我的目标是有一个类似于BackgroundWorker的东西,可以按顺序运行 提前谢谢

我的问题很简单,我有一个类,它包含一个类型为
observedcollection
的(私有)对象,现在我想运行一些线程(按顺序,因此是
ThreadPool
而不是
BackgroundWorkers
),它们向
observedcollection
添加新项

如果
observedcollection
将是一个
ProgressBar
,那么一切都将非常简单(->调用),但我不知道如何调用
observedcollection
对象

我的目标是有一个类似于
BackgroundWorker
的东西,可以按顺序运行


提前谢谢。

我建议使用
任务
对象进行后台操作,并使用
任务调度程序将更新排队到UI线程。从CurrentSynchronizationContext

可以像这样安全地同步对集合的访问:

lock (myCollection) {
    myCollection.InsertItem(0, myItem);
}
ObservableCollection<StatusItem> _listStatus = 
       new ObservableCollection<StatusItem>();

一次只能有一个线程修改集合。确保将使用集合的任何代码放置在锁块内部。

如果不创建自己的集合类,就无法真正做到这一点


有一些线程安全的observable集合的实现可用:

假设您想向observable集合添加StatusItem项。在用户控件的.cs文件中,可以这样声明它:

lock (myCollection) {
    myCollection.InsertItem(0, myItem);
}
ObservableCollection<StatusItem> _listStatus = 
       new ObservableCollection<StatusItem>();
ObservableCollection\u listStatus=
新的可观察集合();
然后,您可以声明一个方法来添加项,如下所示:

private void AddStatus(StatusItem item, bool useDispatcher)
{
    if (useDispatcher) {
        Dispatcher.BeginInvoke(DispatcherPriority.Send, 
           new ThreadStart(() => AddStatus(item, false)));
        return;
    }

    if (_listStatus.Count > MaxItemsToHoldInList) {
        // maybe you have a more efficient way to do this
        for (int i = 0; i < BlockOfItems; i++ ) _listStatus.RemoveAt(0);
    }

    _listStatus.Add(item);

    if (_scrollIntoView) listStatus.ScrollIntoView(item);
}
private void AddStatus(StatusItem项,bool usedpatcher)
{
如果(使用调度程序){
Dispatcher.BeginInvoke(DispatcherPriority.Send,
新的ThreadStart(()=>AddStatus(item,false));
返回;
}
如果(_listStatus.Count>MaxItemsToHoldInList){
//也许你有更有效的方法来做这件事
对于(inti=0;i
我有一些自由,所以也许你不需要这些。基本上,如果要从工作线程内部调用此方法,则必须使用dispatcher将修改推迟到到达用户线程(这听起来像是您想要做的)。您可能已经发现,如果不使用dispatcher线程,您的更新就无法进入GUI。当然,如果您在用户线程中处于活动状态(例如,响应鼠标单击),则可以在调用此方法时设置
usedpatcher=false


我个人经常使用可观察的集合来反馈给用户,因此,在我的例子中,我限制了用户能够看到的窗口。一次删除一个包中的项目是为了提高性能,而您实际上是在清除这些状态消息。我还检查用户是否将拇指放在显示这些项目的列表控件的底部。如果是这样,那么我将
\u scrollIntoView
设置为true,以保持最底层的项处于视图中。

是的,我已经查看了那些线程安全的可观察集合,但是存在一些问题(无论是使用还是实现),如果其他所有方法都失败,我将更努力地尝试其中一个。现在这非常有趣,晚饭后我会试试。是的,很简单,但老实说,@Stephen Cleary的解决方案看起来更符合时代,在WPF和WinForms中都能很好地工作。是的,我正在看它。无论如何谢谢你!我看了一下,但这描述了如何并行使用任务,如何“动态”生成新任务(即每次单击按钮)并将其放入队列?
task.Factory.StartNew
创建新任务。请记住,这涉及两个任务:一个执行后台操作,另一个执行对
ObservableCollection
的实际更新;只有“更新”任务才应使用
任务调度程序