To answer your stated question: to replace a foreach loop with a for loop, replace:
foreach (KeyValuePair<decimal, MemoryStream> tt in profileDic)
{
//...
}
with
for (var i=0; i < profileDic.Count, i++)
{
KeyValuePair<decimal, MemoryStream> tt = profileDic.ElementAt(i);
//...
}
To use this you'd also need to include a using System.Linq;
statement in your code.
That said, this assumes that the order of elements in your dictionary will not change; which is not guaranteed (unless you're using a SortedDictionary
or OrderedDictionary
).
A better approach is therefore:
[decimal[]]keys = profileDic.Keys;
for (var i=0; i < keys.Count, i++)
{
KeyValuePair<decimal, MemoryStream> tt = profileDic[keys[i]];
//...
}
But this adds more overhead / likely pushes the for
loop's time over that of the foreach
loop / is a micro-optimisation that won't solve your real performance issue.
Per comments, the loop is likely not your problem, but what's occurring within that loop (if in this part of the code at all).
We don't know enough about your code to comment on it, so it's likely best that you investigate yourself; e.g. using the performance analysis techniques described here: https://msdn.microsoft.com/en-us/library/ms182372.aspx
I've refactored your code to make it more readable (i.e. by pulling the UI updates into their own methods, so they don't clutter the main thread).
I also moved those operations which look like they wouldn't need to be updated each iteration outside of your loop... but without knowing your code this is pure guesswork / so no guarantees.
Finally I removed your code to alter the priority of the current thread at the end of each iteration. Playing with thread priorities is not a good way to fix slow code; there are only certain cases where it's appropriate, and seeing it's context here I'm over 99% certain that this is not one of those cases.
//...
featuresForVerification = ExtractFeatures(Sample, DPFP.Processing.DataPurpose.Verification); //since this appears unaffected by our profileDic values, let's initialise once
if (featuresForVerification != null)
{
DPFP.Verification.Verification verificator = new DPFP.Verification.Verification();
foreach (KeyValuePair<decimal, MemoryStream> tt in profileDic)
{
string key = tt.Key.ToString(); //we use this a lot, so let's only convert it to string once, then reuse that
UIReportCurrentKey(key);
temp = new DPFP.Template(tt.Value);
DPFP.Verification.Verification.Result result = new DPFP.Verification.Verification.Result();
verificator.Verify(featuresForVerification, temp, ref result);
UIReportMatch(result, key);
//if a match were found, would we want to keep comparing, or exit on first match? If the latter, add code to record which record matched, then use break to exit the loop
UIIncremementProgressBar();
}
} else {
throw new NoFeaturesToVerifyException("The verfication tool was not given any features to verify");
//alternatively set progress bar to complete / whatever other UI actions you have /
//whatever you want to happen if no features were selected for comparison
}
//...
#region UI Updaters
/*
I don't know much about winforms updates; have a feeling these can be made more efficient too,
but for the moment just shoving the code into its own functions to make the main method less
cluttered with UI logic.
*/
// Adds the key of the item currently being processed to the UI textbox
private void UIReportCurrentKey(string key)
{
this.Invoke(new Function(delegate()
{
textBox1.Text += "\n" + key;
}));
}
private void UIReportMatch(DPFP.Verification.Verification.Result result, string key)
{
if (result.Verified)
{
this.Invoke(new Function(delegate()
{
MessageBox.Show("FAR " + result.FARAchieved + "\n" + key);
}));
}
/*
else
{
this.Invoke(new Function(delegate()
{
MessageBox.Show("No Match");
}));
}
*/
}
private void UIIncremementProgressBar()
{
this.Invoke(new Function(delegate()
{
progressBar1.Value++;
}));
}
#endregion UI Updaters
#region Custom Exceptions
public class NoFeaturesToVerifyException: ApplicationException
{ //Choose base class appropriately
public NoFeaturesToVerifyException(): base() {}
public NoFeaturesToVerifyException(string message): base(message) {}
//...
}
#endregion Custom Exceptions