Parallel.ForEach and ListView Control
I am having an issue getting the Parallel.ForEach to work properly. I have a listview control that loads a files contents or mutliple files contents (each file represents a log file) into a richtextbox. Had it all working with a Foreach loop but decided that the parallel operation would cut down on the loadtime when loading 100+ files.
Here is the code block I was using for the foreach loop. How do I get a Parallel.Foreach working?
//Set cursor to WaitCursor Style
this.Cursor = Cursors.WaitCursor;
//Clear Messages RichTexBox
this.rtbMessages.Clear();
//Loop through each selected file
foreach (ListViewItem Item in lvMessageFiles.Items)
{
//Check if item is selected in the listview
if (Item.Selected && rtbMessages.TextLength < rtbMessages.MaxLength)
{
//Get Path to message file
filename = String.Format("{0}\\Data\\Log\\{1}.log", Global.AppPath, Item.SubItems[0].Text);
//Set Timeline Events calendar to selected items created date
cvTimeline.ShowDate(Convert.ToDateTime(lvMessageFiles.SelectedItems[0].SubItems[2].Text));
//Check if file exists
if (File.Exists(filename))
{
//streamreader to read the file
reader = new StreamReader(filename);
//to copy the read content in to richtextbox
string MessageContents = String.Format("{0}\n{1}\n", ("file:///" + filename.Replace(" ", "%20").Replace("\\", "/")), reader.ReadToEnd());
rtbMessages.Text += MessageContents;
// closing streamreader
reade开发者_高级运维r.Close();
}
}
}
//Set cursor to WaitCursor Style
this.Cursor = Cursors.Default;
2 problems with what you are doing.
1) with this specific code, you are trying to modify UI from a background thread which is not allowed
2) this scenario isn't a good candidate for parallelization anyhow because you're performace is "I/O bound" to a single hard drive. if you want to speed up load time, split the files onto multiple hard drives and then parallelization may be worthwhile
see Is Parallel File.Read Faster than Sequential Read?
You're not allowed to update UI from a non-UI thread, which threads in a Parallel.ForEach
obviously will be. Instead use the Invoke method to set the Text
of rtbMessages
and call cvTimeline.ShowDate
I am experiencing dejavu with this question... Anyway, take a look at this blog article. It's very simple to my taste but does exactly what you are trying to achieve - update UI while working with concurrent collections using new .NET 4 parallel mechanisms. Though not ForEach but Task.
http://blogs.msdn.com/b/csharpfaq/archive/2010/06/18/parallel-programming-task-schedulers-and-synchronization-context.aspx
精彩评论