3

I'm using 32 tasks in one thread to manage a big datatable (I'm splitting it in 32 parts). I'm launching my tasks like this :

var task1 = Task.Factory.StartNew(() => MyFunction(args));
var task2 = Task.Factory.StartNew(() => MyFunction(args));
...
Task.WaitAll(task1, task2, ...);

I want to display the user how many do he have to wait. Each time a task is over I want to increment a value to display something like : "Wait (1/32)", then "Wait(2/32)" ... etc

How can I check when a task is complete with my code ? Thanks.

BlackAlpha
  • 376
  • 1
  • 5
  • 15
  • Tasks can have a `IProgress` which you need to implement [msdn](https://msdn.microsoft.com/en-us/library/hh138298.aspx) – Callum Linington Jan 18 '17 at 09:19
  • You should use `Task.Run` instead of StartNew. More importantly, you should use `await Task.WhenAll(...)` instead of `Task.WaitAll(...)` to avoid blocking your current thread – Panagiotis Kanavos Jan 18 '17 at 09:21
  • You can increment counter when starting new task and decrement it with `Task.ContinueWith`. – Sinatr Jan 18 '17 at 09:22
  • @Sinatr why use `ContinueWith` ? Anyway, that doesn't help with reporting progress. .NET's IProgress/Progress mechanism ensures events and callbacks are raised in the proper thread – Panagiotis Kanavos Jan 18 '17 at 09:24
  • @PanagiotisKanavos, why do you think this question is about task progress? It's about completed tasks. – Sinatr Jan 18 '17 at 09:24
  • @Sinatr tasks that don't need `ContinueWith`. They did in .NET 4, which is no longer supported. .NET has its own reporting mechanism *and* a better way to detect the end of a task with `await` – Panagiotis Kanavos Jan 18 '17 at 09:25
  • I edited my question, I just want to check when a task is done to increment a value, not a real progress. @Sinatr All my task start at the same time, no ? – BlackAlpha Jan 18 '17 at 09:26
  • @BlackAlpha using IProgress *is* the correct way to do this - how are you going to update the counter in a thread-safe way? Or update the UI in a thread-safe manner? Far simpler to use the progress event or handler to update a counter on the UI thread – Panagiotis Kanavos Jan 18 '17 at 09:27
  • @BlackAlpha if you just want to increment a field or variable you could use Interlocked.Increment but that doesn't solve the problem of displaying the progress messages – Panagiotis Kanavos Jan 18 '17 at 09:29
  • @PanagiotisKanavos Currently I'm doing like this ```Invoke(new MajStatut(MajStatutTxt), "Wait ...");``` – BlackAlpha Jan 18 '17 at 09:29
  • @PanagiotisKanavos, duplicate is clearly **not** about what OP is asking for. As for `ContinueWith` it was the first idea what come into mind. You are right, counter can be decremented in the lambda (at the end). My guess, OP don't really care if `Task` is really completed, he simply wants to know when job (`MyFunction()`) is done. – Sinatr Jan 18 '17 at 09:29
  • @BlackAlpha you don't need to do this. Just check the duplicate question. – Panagiotis Kanavos Jan 18 '17 at 09:30
  • @Sinatr just read the duplicate question. You'll see that this is a very easy way to do exactly what the OP asks. The IProgress interface was created precisely for this purpose - so that *any* asynchronous operation, not just tasks, can report progress. And progress doesn't mean a percentatge. It can transfer an entire data object and mean termination – Panagiotis Kanavos Jan 18 '17 at 09:30
  • @PanagiotisKanavos, I disagree =P. It would be really better if you would post answer here instead. Because it's not clear to me and probably won't be clear to future readers. – Sinatr Jan 18 '17 at 09:31
  • @Sinatr the duplicate is clear. Also check the MSDN docs on IProgress – Panagiotis Kanavos Jan 18 '17 at 09:32
  • @Sinatr you can also check [Async in 4.5: Enabling Progress and Cancellation in Async APIs](https://blogs.msdn.microsoft.com/dotnet/2012/06/06/async-in-4-5-enabling-progress-and-cancellation-in-async-apis/) from the .NET Blog. – Panagiotis Kanavos Jan 18 '17 at 09:33
  • @PanagiotisKanavos, that's the point. I don't understand (does OP?) how `IProgress`, used to report **task progress** is useful to report **task competition** only. Hmm.. perhaps you mean the way how to display that counter? But that's another story, imho a simple polling would be more than enough in this case. – Sinatr Jan 18 '17 at 09:33
  • @PanagiotisKanavos I don't understand, what IProgress will return with a Task object ? A number ? – BlackAlpha Jan 18 '17 at 09:35
  • @Sinatr adding similar answers when there are many duplicates already, blog posts and guides just generates noise. That's why there is a rule against duplicates – Panagiotis Kanavos Jan 18 '17 at 09:36
  • 1
    @PanagiotisKanavos, I already voted to reopen. To me it doesn't looks like duplicate (nor I understand how it can be used by OP). Tell us please. – Sinatr Jan 18 '17 at 09:37
  • @BlackAlpha anything you want, it's a generic interface. You can send a number, a string, or a custom class. The *handler* runs on the UI thread though, so it can simply update a counter and change the label text without `Invoke` or locking – Panagiotis Kanavos Jan 18 '17 at 09:37
  • 1
    @PanagiotisKanavos Regarding the number of tasks I have, how can I use IProgress with each of them ? Can you give me just one example ? – BlackAlpha Jan 18 '17 at 09:38
  • 2
    I do not believe this is a duplicate. one is the progress of a single task, the other is about finding how many are complete from a set of many tasks. Should be reopened – MartinM Jan 18 '17 at 09:41
  • 1
    `var task1 = Task.Factory.StartNew(() => MyFunction(args)).ContinueWith(x => Console.WriteLine("Wait ({0}/32)", Interlocked.Increment(ref counter)));` Obviously you may want to count number of tasks first rather than setting it to 32 everytime & this is assuming you want to write to console. – MartinM Jan 18 '17 at 09:51
  • I was thinking my question was blocked, I will check with your code, thanks for your help @MartinMilsom – BlackAlpha Jan 18 '17 at 10:02

0 Answers0