ObservableCollection不会在平行内部更新。
我有一个名为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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我为自己要说的话感到骄傲。但是,借助您所有的所有工作和建议,我觉得我应该做出解释。顺便说一句,谢谢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.
问题在于
Parallel.Foreach
方法是一种同步方法,可在并行操作期间阻止当前线程¹。当UI线程被阻止时,UI将变得无反应。您可以尝试将并行循环卸载到 /code> ,通过使用task.run
方法:此调用应在
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 theThreadPool
, by using theTask.Run
method:This call should be in an
async
method withTask
return value, or in anasync 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 theParallel.ForEach
method, because the default is-1
, which means unlimited parallelism. Which practically means that the limit is theThreadPool
availability, in other words theThreadPool
becomes saturated.¹ To be more precise the current thread participates in the parallel processing as a worker thread.