-1

As I got the processes to work I ran onto possibly a Threading problem when I was trying to add a ProgressBar to give the user some clue that the process hasn't crashed. Since this is enough, an Indefinite ProgressBar in just fine for me.

 <ProgressBar x:Name="ProcessProgress" Minimum="0" Maximum="100" Visibility="Hidden" IsIndeterminate="False" Width="305" Height="20" Margin="240,214,248,10"></ProgressBar>

I tried to initiate a determinate length progress bar which is not visible before the Start button is clicked :

private void Start_Click(object sender, RoutedEventArgs e)
{
    ...
    //process starts here
    var fP = new FileProcessor();
    ProcessProgress.IsIndeterminate = true;
    ProcessProgress.Visibility = Visibility.Visible;

    ...
    //finally show the progressbar as full when done
    ProcessProgress.IsIndeterminate = false;
    ProcessProgress.Value = ProcessProgress.Maximum;

}

It just runs the whole process and my bar doesn't show up.

How can I spawn a progress bar during the process ?

scharette
  • 9,437
  • 8
  • 33
  • 67
  • async await is the way to go. you shouldn't do the actual operations on the code behind anyways. It should be done thru ViewModel + command pattern. I know its lots of things to learn but if you gonna do it, better do it right :) – Steve Jul 23 '18 at 15:03
  • 1
    @Steve Yes, you are totally correct and I appreciate the gesture. May I ask for a proper tip(maybe a link or bibliography, series of videos)? I'd like to get involved pretty fast since at the beginning of next month I need to connect it to an SQL server and none of my group partners actually have fingers to code(if you know what I mean) . –  Jul 23 '18 at 15:09
  • keywords: "MVVM", "WPF ICommand", "async await", "c# Task". google the tutorial for those and get a good understanding of what they are and how to properly use them then you are good to start. Might take 2+ weeks to finish everything. Sql will take months to master so just keep that in mind. – Steve Jul 23 '18 at 15:13
  • I cannot say if this will work for your particular case, but see my [answer](https://stackoverflow.com/a/51212664/7692463) where I talk about this particular topic. – scharette Jul 23 '18 at 15:24
  • @scharette Thank you for your Comment. I'll take a peak soon and hopefully it will pay dividens, since we are really really really running out of time. :( –  Jul 23 '18 at 15:27
  • @VargaElőd I'll will post a boiler plate for you removing the unnecessary stuff of the linked answer. – scharette Jul 23 '18 at 15:27
  • @scharette Huge thanks, I'll stay on alert this evening. Would be nice if I could get atleast the prototype up and running tomorrow morning. –  Jul 23 '18 at 15:31
  • @VargaElőd before saying "thank you", that code has multiple serious bugs. You *don't* need that extension at all, the code before and after `await Task.Run()` runs on the UI thread. Just modify the progress bar. `async void` should only be used for event handlers, never for other methods – Panagiotis Kanavos Jul 25 '18 at 08:56

1 Answers1

1

The problem is that all of your code runs in the UI thread. The UI has no chance to update itself before the entire process finishes.

You can use Task.Run() to run a heavy job in the background without blocking the UI. You can use the await keyword to await that task to complete without blocking the UI. Once the task completes, you are back in the UI thread where you can modify the UI again.

A quick and dirty fix for this event handler would be :

private async void Start_Click(object sender, RoutedEventArgs e)
{
    ProcessProgress.IsIndeterminate = true;
    ProcessProgress.Visibility = Visibility.Visible;
      ...
    await Task.Run(()=>
    {
        //process starts here
        var fP = new FileProcessor();

        ...
    });

    //We are back in the UI thread, we can modify the UI
    ProcessProgress.IsIndeterminate = false;
    ProcessProgress.Value = ProcessProgress.Maximum;
}

No need to use Invoke to get back to the UI thread, that's the job of await itself.

A note about async void. It's ONLY meant for event handlers or similar methods. You can't await an async void method which means you can't even get any exceptions if something goes wrong. Asynchronous methods that return nothing should have the async Task signature.

If you want to report progress you can use the IProgress interface and the Progress class as explained here. The Progress class will call a callback or raise an event on the thread it was created. The payload can be any class, not just a percentage

It's best to move the reporting code to separate methods, to keep the button handler clean. The code can look like this :

//The progress class
class FileProgress
{
    public string FileName{get;set;}
    public int Progress{get;set;}
    public string Message{get;set;}

    public FileProgress(string fileName,int progress,string message)
    {
        FileName=filename;
        Progress=progress;
        Message=message;
    }
}

//In the form itself
private void ReportStart()
{
    ProcessProgress.IsIndeterminate = true;
    ProcessProgress.Visibility = Visibility.Visible;
}

private void ReportEnd()
{
    ProcessProgress.IsIndeterminate = false;
    ProcessProgress.Value = ProcessProgress.Maximum;
}

private void ReportProgress(FileProgress progress)
{
    ProcessProgress.Value =progress.Progress;        
    PanelStatus.Text = $"Working on {progress.FileName} : {progress.Message}";
}

The event handler can now look like this :

private async void Start_Click(object sender, RoutedEventArgs e)
{
    ReportStart();

    IProgress<FileProgress> progress=new Progress<FileProgress>(ReportProgress);
      ...
    await Task.Run(()=>
    {
        //process starts here
        var fP = new FileProcessor();

        foreach(var file in someFiles)
        {
              progress.Report(new FileProgress(file,0,"Starting");
              //Do some processing
              progress.Report(new FileProgress(file,100,"Finished");
        }
        ...
    });

    //We are back in the UI thread, we can modify the UI
    ReportEnd();
}
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • I believe this is the moment I should really say thank you. Implementing this approach eliminated all my bugs and now I have only one thing to solve which is another question to be asked. Huge ups for this answer, Sir. –  Jul 26 '18 at 13:11