0

I have this simple for:

        for (int i = 0; i < nro_archivos; ++i) //Cargar el objeto img
        {
            string nombrearchivo = archivosdicom[i].FullName;
            img.Add(new ImagenDicom(nombrearchivo));
            Progress_Bar_Loading_Images.PerformStep();
        }

followed by this:

   decimal[] sliceseparation_imagen = new decimal[img.Count - 1];
        for (int i = 0; i < img.Count; i++)
        {
            if (i < img.Count - 1)
            {
                sliceseparation_imagen[i] = Math.Abs(img[i + 1].Z - img[i].Z);
            }
        }
        sliceseparation_promedio = sliceseparation_imagen.Average();

Now, my challenge is: I implemented Paralell For but can't use the progressbar.. so I was thinking on using BackgroundWorker but the problem is that the operation right after the for is dependent on the load of the object img which happens in the for so until that's not done I can't continue. My understanding of BackGroundWorker is that it executes in the background while the main program continues its execution, so this approach will bring errors when trying to access an img object that has not been created by the time the main program reaches the code outside the for.

Does it worth to use Background Worker in this case to speed up the load of the img object? if it does, how do I wait until the backgroundworker has done its job to then continue with the execution of the main program? I need to report progress on the for operation to the user so using a parallel for without something that would allow me to report back to the user won't work. Thanks, Matias.

Matias
  • 539
  • 5
  • 28
  • One thing about Background Worker is that its purpose is to perform long computational work in the background, while updation of UI can be handled through the main thread. And you can handle events like DoWork, ProgressChanged - to report back on the status which can be used to update Progressbar in your case – Justin Samuel Sep 15 '16 at 20:23
  • Thanks Austin, that works fine for me, the issue is with the code that continues to execute in the main thread, it uses the object that is being loaded in the for (which would be inside the background worker if I decide to implement that) so until it doesn't finish, I can't really do much otherwise it will throw errors trying to access objects that have not been loaded still – Matias Sep 15 '16 at 20:28

2 Answers2

1

If I understood the problem right here, you have one set of work when you're loading the image, you can care less about this one and pretend this can happen in parallel anyway but the problem is you need to report progress.

And after loading it you have one other block of work you need to do so, you can do it right away or you can do it after all the images are loaded.

Instead of parallel, you can go for Tasks. Access UI thread through a UI dispatcher so you don't have to worry about UI thread access issues.

var tasks = new List<Task>
{
    Task.Run(() => { 
     // Block 1 
     // Use a proper dispatcher here to access the UI thread so you can report your progress}),
};
Task.WaitAll(tasks);

Now you have got your loads done, and you can progress with your second block of work.

But, as I can see you only need the average out of it and you don't need proper order to get average.

    var tasks = new List<Task>
        {
            Task.Run(() => { /* for loop logic #1 */})
            .ContinueWith((x)=> {
                // Get your task result and execute second block 
            })
        };
   Task.WaitAll(tasks);

Now you have a continued task with it and all you have to do is call for an average after this is done.

You can go with two separate blocks too. I figured as these tasks are intertwined, why can't you just continue with one task anyway.

Swagata Prateek
  • 1,076
  • 7
  • 15
0

Using Tasks may help

var tasks = new List<Task>
{
    Task.Run(() => { /* for loop logic #1 */
            /* when interacting w/UI either use Dispatcher
               for WPF for control.Invoke in winforms */
        }),
    Task.Run(() => { /* for loop logic #2 */})
};
Task.WaitAll(tasks.ToArray());
Paul Tsai
  • 893
  • 6
  • 16
  • This may work, but I still have the issue of reporting progress with the progressbar. It will access it from outside the main thread causing an error. – Matias Sep 15 '16 at 20:57
  • When updating the progress bar, invoke it on the UI thread to avoid the cross thread exception. There are different ways to do this (wpf vs winforms, etc) The following link may help. http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c – Paul Tsai Sep 15 '16 at 21:02