1

I'm trying to go through my event logs with a Parallel.ForEach. But at random it stops with the error IndexOutOfRangeException on the foreach.

this one:

foreach (EventLogEntry message in evlog.Entries)

Sometimes it stops with the first time it goes through the loop and sometimes after already gone through the loop 44 times.

Also I sometimes get the error that the given ID already exists.

Here's my full code:

string ID = null;
Logs.Add("System", 0);
Logs.Add("Application", 1000);
Logs.Add("Setup", 2000);
Logs.Add("Forwarded Events", 3000);  

EventLog evlog = new EventLog();
evlog.MachineName = ".";  

Parallel.ForEach(Logs.Keys, logname =>
{
    System.Threading.Thread.Sleep(1000);
    evlog.Source = logname;
    string lognameWithoutSpaces = logname.Replace(" ", "");

    foreach (EventLogEntry message in evlog.Entries)
    {
        string type = message.EntryType.ToString();
        if (type == "0" | type == "Warning")
        {
            ID = lognameWithoutSpaces + "_" + Logs[logname].ToString();
            Console.WriteLine("ID: " + ID);
            dictLogs.Add(ID, new List<string>());
            dictLogs[ID].Add(evlog.Log);
            dictLogs[ID].Add(message.Source);
            dictLogs[ID].Add(message.InstanceId.ToString());
            dictLogs[ID].Add(type);
            dictLogs[ID].Add(message.UserName);
            dictLogs[ID].Add(message.TimeGenerated.ToString());
            dictLogs[ID].Add(message.Category);
            dictLogs[ID].Add(message.MachineName);
            dictLogs[ID].Add(message.Message);
            Logs[logname]++;
        }
    }
});
dictLogs.Clear();

This is what I see in de console:

ID: ForwardedEvents_3000
ID: System_0
ID: Setup_2000
ID: Application_1000
'DashboardBackEnd.vshost.exe' (CLR v4.0.30319: DashboardBackEnd.vshost.exe):    Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.resources\v4.0_4.0.0.0_nl_b77a5c561934e089\System.resources.dll'. Module was built without symbols.
A first chance exception of type 'System.Collections.Generic.KeyNotFoundException' occurred in mscorlib.dll
A first chance exception of type 'System.IndexOutOfRangeException' occurred in System.dll

3 Answers 3

3

dictLogs are being added to at the same time by multiple threads. If this is a normal dictionary this will give you issues.

Ask yourself what happens when

dictLogs.Add(ID, new List<string>());

is called at the exact same time.

You have the same kind of issue with

Logs[logname]++;

where the same entry will be updated by multiple threads. However this should not cause an IndexOutOfRangeException but will cause incorrect counts.

Your ID already exists exception I think is because of this

ID = lognameWithoutSpaces + "_" + Logs[logname].ToString();

Logs[logname] could have the same count at the same time. Hence this will cause duplicate keys to be entered

Also

evlog.Source = logname;

might not cause any exceptions but it will give you incorrect results because it might be changed by another thread before it reaches the loop:

foreach (EventLogEntry message in evlog.Entries)

In all honesty I would say take out the Parallel loop before you blow up the universe.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. I promise you that I won't blow up the universe so I will take out the parralel loop :)
1

I expect the collection is not thread safe, what makes you think it is?

Also it is very possible that your actions when processing a message changes the collection in some unexpected way.

What are you trying to achieve by writing complex multi threaded code when 1 thread would do the job?

1 Comment

I tink it is but apparently not. I'm trying to do all the logs at the same time but I think i'm going for 1 source at the time and not all at once.
1

Each instance of the parallel loop is writing to the same evlog. So one looping is setting the Source while another loop is already running.

3 Comments

That looks like a good reason. But can it give because of that a IndexOutOfRangeException ? It looks like it but still, can it?
Yes, because you're changing the underlying collection. Suddenly there may be less items in the collections, causing the IndexOutOfRangeException.
@SebastiaanMegens. This is not true. The worst you will get is InvalidOperationException Collection was modified like you do when a collection is modified when doing a for loop. One will not get a IndexOutOfRangeException in this case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.