0

I am trying to understand how I might be able to make better use of the .Net 4.5 TPL. Traditionally I used to manage the threads the old-school way, queueing and managing the threads directly.

I have created a silly program to explore the TPL, however, the code only seems to execute the last of the tasks added to my tasks list - I cannot determine why:

class Program {
    static void Main(string[] args) {

        var a = new A();
        var b = new B();

        var tasks = new List<Task<string>>();
        for (int j = 33; j < 64; j++) {
            tasks.Add(Task.Run(() => a.Go(j, 20)).ContinueWith((i) => b.Do(i)));
        }
        var finalTask = Task.Factory.ContinueWhenAll(tasks.ToArray(), r => {
            foreach (var t in r)
                Console.Write(t.Result);
        });

        finalTask.Wait();

        Console.WriteLine("Finished.");
        Console.ReadLine();

    }
}

public class A {
    public int Go(int chr, int loops) {
        for (int i = 0; i < loops; i++) {
            Thread.Sleep(10);
            Console.Write((char)chr);
        }
        return loops;
    }
}

public class B {
    public string Do(Task<int> value) {
        string s = "";
        for (int i = 0; i < value.Result; i++) {
            s = s + "a";
        }
        return s;
    }
}

Any ideas why the other threads do not execute?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Ash
  • 24,276
  • 34
  • 107
  • 152
  • I hate that I have a great answer that addresses a lot more than just the capturing issue and I can't post because the damn question gets marked as a duplicate while writing it up. – Berin Loritsch Jun 03 '16 at 14:22
  • I highly recommend looking at TAP than wasting your time with TPL. It's built on the same infrastructure but smooths out a _lot_ of the rough edges. I had an answer that described how to do your little experiment with TAP, but I can't post it because this was marked as a duplicate. – Berin Loritsch Jun 03 '16 at 14:24

1 Answers1

2

You have to capture the running variable j within the closure context:

for (int j = 33; j < 64; j++) {
        var num = j;
        tasks.Add(Task.Run(() => a.Go(num, 20)).ContinueWith((i) => b.Do(i)));
    }

See also Captured variable in a loop in C#

Community
  • 1
  • 1
JanDotNet
  • 3,746
  • 21
  • 30