1

It seems like I am getting threading errors as a result of an inconsistent state of my IEnumerable. Specifically, List<T>.

Here's my workflow:

List<string> IDs = getIDs();
RunTask(IDs);
RunTask(IDs);

public void RunTask(List<string> IDs)
{
    TaskScheduler scheduler = new TaskScheduler();
    TaskFactory factory = new TaskFactory(scheduler);
    var tasks = IDs.Select(name => factory.StartNew(() => action(name))).ToArray();
    Task.WaitAll(tasks);
}

I am getting a generic error on my WaitAll() call.

My thinking is that I am getting some sort of unsynchronized IEnumerator, and that I need to make a copy of my List via Array.CopyTo(), then pass it into my multiple threads.

This is my exception:

Error: One or more errors occurred.
One or more errors occurred.
at System.Threading.Tasks.Task.WaitAll(Task[] tasks, Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.WaitAll(Task[] tasks, Int32 millisecondsTimeout)
at System.Threading.Tasks.Task.WaitAll(Task[] tasks)

Any thoughts on this matter?

Codeman
  • 12,157
  • 10
  • 53
  • 91
  • Have you considered using something like a Mutex to block multiple threads from accessing the list simultaneously? – Corey Oct 12 '12 at 18:53
  • You don't, it's not safe. See the answers to this question for some good information. http://stackoverflow.com/questions/6601611/no-concurrentlistt-in-net-4-0 Edit - I didn't notice you weren't writing to the list. Multiple readers is fine. – asawyer Oct 12 '12 at 18:55
  • Unfortunately, I need both threads to access the data in the list. – Codeman Oct 12 '12 at 18:55
  • 2
    You can read from a list perfectly safely from multiple threads. You're not mutating the list here so it's fine. The problem is in code not posted (like whatever `action` is). – Servy Oct 12 '12 at 18:59
  • 2
    @tkeE2036 it seems like people are just downvoting questions they don't like, regardless of quality – Mike Park Oct 12 '12 at 19:00
  • Oh, and technically you're not even accessing the `List` from multiple threads. The two `RunTask` methods aren't run in parallel because of the `WaitAll`. The tasks that are run in parallel don't access the list directly, just strings that the list references (which is fine, and couldn't ever break anything since `string`s are immutable. – Servy Oct 12 '12 at 19:00
  • @climbage yes, downvotes happen far more often than they should... seems like most don't even read the question and assume that I'm too lazy to test it myself :/ – Codeman Oct 12 '12 at 19:56

1 Answers1

7

I don't think this is a threading error - it should be safe as long as each task does not modify the IDs list. Task.WaitAll() throws an AggregateException if any of the waited tasks throw an exception or are cancelled.

You can access the InnerExceptions on the exception to see what the error(s) are.

try
{
    Task.WaitAll(tasks);
}
catch(AggregateException ex)
{
    foreach(Exception in ex.InnerExceptions) { ... }
}
Lee
  • 142,018
  • 20
  • 234
  • 287
  • I ended up doing something very similar to this and it fixed my problem by giving me the entire stack trace - turned out my service did not have the correct file permissions. Marking yours as correct, thanks! – Codeman Oct 12 '12 at 19:57