ObservableCollection不会在平行内部更新。

发布于 2025-01-26 20:27:56 字数 2806 浏览 4 评论 0原文

我有一个名为Allvideos的观察力。我正在使用视频模型和Allvideos Collection上使用InotifyPropertychanged。对于文件选择器中的每个文件,我正在并行中运行一种称为processMetadata()的方法。 ProcessMetadata()将新的视频文件模型添加到Allvideos集合中。我遇到的问题是,该方法没有更新Allvideos集合。如果该方法未在并行中执行。

以下是称为平行的方法。foreach:

public void GetVideoFiles()
{                   
    OpenFileDialog openFileDialog = new OpenFileDialog();
    openFileDialog.Multiselect = true;
        
    if(openFileDialog.ShowDialog() == true)
    {              
        List<string> files = new List<string>();
        foreach(string file in openFileDialog.FileNames)
        {
            files.Add(file);                        
        }
        Parallel.ForEach(files, f => ProcessMetaData(f));
        bool extractTrigger = true;
        while (extractTrigger == true)
        {
            if (AllVideos.Count == files.Count)
            {
                Debug.WriteLine("VALUES ARE EQUAL !!!!!!!!!!");
                Parallel.ForEach(AllVideos, v => ExtractFrames(v.VideoPath, v.FrameDestinationPath));
                extractTrigger = false;
            }
        }                                
    }            
}

以下是并行的方法。foreach:

private void ProcessMetaData(string fileName)
{                   
    var metaData = Helpers.MetaHelper.getExifDataViaTool(fileName);            
    Guid guid = Guid.NewGuid();
    var destinationDirectory = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"FCS\Temp\" + guid.ToString() + @"\");
    if (!System.IO.Directory.Exists(destinationDirectory))
    {
            System.IO.Directory.CreateDirectory(destinationDirectory);
            System.IO.Directory.CreateDirectory(destinationDirectory + @"\Thumb\");
    }
    else
    {
        MessageBox.Show("Directy already exist");
    }
        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>
    {
        AllVideos.Add(new Models.VideoFileModel()
        {
            VideoName = metaData["File Name"],
            VideoPath = metaData["Directory"].Replace("/", @"\") + @"\" + metaData["File Name"],
            VideoDuration = Helpers.MetaHelper.ParseExifDuration(metaData["Duration"]),
            VideoCreated = Helpers.MetaHelper.ParseExifDateModified(metaData["Date/Time Original"]),
            VideoThumbPath = destinationDirectory + "Thumb\\thumb.jpg",
            FrameDestinationPath = destinationDirectory
            //VideoFrameRate = Helpers.MetaHelper.GetFrameRate(fileName)
        });   
    }));    
    NotifyPropertyChanged(nameof(AllVideos));    
    ProcessThumb(fileName, destinationDirectory);   
}

关于为什么未更新Allvideos的任何想法?我的代码陷入了时循环,因为allvideos.count始终等于0,而不是file.count。

感谢任何建议!被困在这一个大约8个小时上。

I have an ObservableCollection called AllVideos. I am using INotifyPropertyChanged on the video model as well as the AllVideos collection. For each file in a File Picker, I am running a method called ProcessMetaData() in a Parallel.ForEach. ProcessMetaData() adds new video file models to the AllVideos collection. The problem I am having is that the AllVideos collection is not being updated by the method. It works fine if the method is not executed in the Parallel.Foreach.

Below is the method that calls the Parallel.Foreach:

public void GetVideoFiles()
{                   
    OpenFileDialog openFileDialog = new OpenFileDialog();
    openFileDialog.Multiselect = true;
        
    if(openFileDialog.ShowDialog() == true)
    {              
        List<string> files = new List<string>();
        foreach(string file in openFileDialog.FileNames)
        {
            files.Add(file);                        
        }
        Parallel.ForEach(files, f => ProcessMetaData(f));
        bool extractTrigger = true;
        while (extractTrigger == true)
        {
            if (AllVideos.Count == files.Count)
            {
                Debug.WriteLine("VALUES ARE EQUAL !!!!!!!!!!");
                Parallel.ForEach(AllVideos, v => ExtractFrames(v.VideoPath, v.FrameDestinationPath));
                extractTrigger = false;
            }
        }                                
    }            
}

Below is the method being called by the Parallel.Foreach:

private void ProcessMetaData(string fileName)
{                   
    var metaData = Helpers.MetaHelper.getExifDataViaTool(fileName);            
    Guid guid = Guid.NewGuid();
    var destinationDirectory = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"FCS\Temp\" + guid.ToString() + @"\");
    if (!System.IO.Directory.Exists(destinationDirectory))
    {
            System.IO.Directory.CreateDirectory(destinationDirectory);
            System.IO.Directory.CreateDirectory(destinationDirectory + @"\Thumb\");
    }
    else
    {
        MessageBox.Show("Directy already exist");
    }
        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>
    {
        AllVideos.Add(new Models.VideoFileModel()
        {
            VideoName = metaData["File Name"],
            VideoPath = metaData["Directory"].Replace("/", @"\") + @"\" + metaData["File Name"],
            VideoDuration = Helpers.MetaHelper.ParseExifDuration(metaData["Duration"]),
            VideoCreated = Helpers.MetaHelper.ParseExifDateModified(metaData["Date/Time Original"]),
            VideoThumbPath = destinationDirectory + "Thumb\\thumb.jpg",
            FrameDestinationPath = destinationDirectory
            //VideoFrameRate = Helpers.MetaHelper.GetFrameRate(fileName)
        });   
    }));    
    NotifyPropertyChanged(nameof(AllVideos));    
    ProcessThumb(fileName, destinationDirectory);   
}

Any ideas as to why AllVideos is not being updated? My code is stuck in the while loop because AllVideos.Count is always equal to 0 and not file.Count.

I would appreciate any advice! Been stuck on this one for about 8 hours.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光沙漏 2025-02-02 20:27:56

我为自己要说的话感到骄傲。但是,借助您所有的所有工作和建议,我觉得我应该做出解释。顺便说一句,谢谢Theodor的信息。我对此并不了解,现在有了更好的理解。

我在Allvideos中为每个视频所拥有的进度键没有移动,因此我只是以为该系列没有被更新。实际上,问题在于,进度栏是在堆栈中,宽度未定义。 Stackpanel将进度键的宽度降低到一个像素,从而使其似乎没有更新。

试图解决这个愚蠢的事情的三天。我只是好奇。我从来没有在软件开发行业工作,因为我是自学的,而仅是用于学习目的的代码项目。在实际行业中,像这样的愚蠢错误是正常的吗?

我想在某个时候改变职业。但是,我在CS上没有教育,也不认为我会被考虑。

I am not proud of what I am about to say; however, with all the work and advice that you have all given, I feel that I owe an explanation. BTW, thank you Theodor for your information about the Parallell.ForEach. I did not know much about it and now have a much better understanding.

The ProgressBar that I have for each video in AllVideos was not moving so I just assumed that the collection was not being updated. Actually, the problem was that the ProgressBar was in a StackPanel and the width was not defined. The StackPanel reduced the width of the ProgressBar to One pixel, making it appear to not update.

Three days of trying to solve this problem over something this stupid. I am just curious. I have never worked in the Software Development industry as I am self taught and just code projects mainly for learning purposes. Are stupid mistakes like this normal in the actual industry?

I would like to change careers at some point; however, I do not have an education in CS and don't think I would even be considered.

幻想少年梦 2025-02-02 20:27:56

问题在于Parallel.Foreach方法是一种同步方法,可在并行操作期间阻止当前线程¹。当UI线程被阻止时,UI将变得无反应。您可以尝试将并行循环卸载到 /code> ,通过使用 task.run 方法:

var options = new ParallelOptions() { MaxDegreeOfParallelism = 2 };
await Task.Run(() => Parallel.ForEach(files, options, f => ProcessMetaData(f)));

此调用应在async方法中,task> task返回值=“ https://learn.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-best-practices-in-sasion-progrogin-programming,programming,Void-Async-void-Void” rel =“ nofollow noreferrer“> async void 事件处理程序。操作启动并且直到结束时,您可能必须禁用某些按钮/菜单,以防止操作运行时用户与UI进行交互。

顺便说一句,我建议 在调用 Parallel.Foreach 方法,因为默认值为-1,这意味着无限的并行性。实际上,这意味着限制是threadpool可用性,换句话说,threadpool变得饱和。

Å更准确地说,当前线程以工作线程为平行处理。

The problem is that the Parallel.ForEach method is a synchronous method that blocks the current thread¹ during the parallel operation. And when the UI thread gets blocked, the UI becomes non-responsive. You could try offloading the parallel loop to the ThreadPool, by using the Task.Run method:

var options = new ParallelOptions() { MaxDegreeOfParallelism = 2 };
await Task.Run(() => Parallel.ForEach(files, options, f => ProcessMetaData(f)));

This call should be in an async method with Task return value, or in an async void event handler. You might have to disable some buttons/menus when the operation starts and until it ends, to prevent the user from interacting with the UI while the operation is running.

Btw I recommend that the MaxDegreeOfParallelism is explicitly specified when calling the Parallel.ForEach method, because the default is -1, which means unlimited parallelism. Which practically means that the limit is the ThreadPool availability, in other words the ThreadPool becomes saturated.

¹ To be more precise the current thread participates in the parallel processing as a worker thread.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文