user12913162
user12913162

Reputation:

How to run a ProgressBar within a method with other methods

I have an issue with ProgressBar being actualized in a separated UI thread...

I have in my program lots of methods, in which I would like to start and stop a progress bar.

Therefore, I put a UI component ProgressBar in my UI and made a model for it, which (after bindings) works fine when called/used standalone in my model classes (i am not working in code behind). The problem arises when I set my Progress model property as indeterminate and then call some other methods: the whole works synchronously and the progressbar gets moving only at the end when exiting the main method.

Here an example of what I want to achieve:

public void MyMethod1()
{
    StartProgress();

    NormalSubMethod1();
    NormalSubMethod2();
    (...)

    EndProgress();
}

public void MyMethod2()
{
    StartProgress();

    NormalSubMethod5();
    (...)

    EndProgress();
}

and here is how my StartProgress() looks like, with what i've tried without success:

public async void StartProgress()
{
    //Task.Run(() => { Progress.IsIndeterminate = true; });

    //await Task.Run(() => Progress.IsIndeterminate = true); // starts moving
}

public async void StopProgress()
{
    Progress.IsIndeterminate = false; // stops moving
}

I know this has to be a problem of not correctly using the async, await and Task things, but I could not yet get it to work. May anyone please help me providing me a hint on how can I accomplish this?

Upvotes: 0

Views: 1026

Answers (1)

Miamy
Miamy

Reputation: 2299

Your NormalSubMethod-s should be asynchronous themselves. Below is an example how it can works. Please take a look how async/await are used here.

XAML

<StackPanel>
    <ProgressBar
        x:Name="progress"
        Width="100"
        Height="30"/>
    <Button Content="Button"
            Width="60"
            Height="30" Click="Button_Click"
            />
    <TextBlock 
        TextWrapping="Wrap" 
        x:Name="textBlock" />
</StackPanel>

Code

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        StartProgress();
        await MyMethod();
        StopProgress();
    }

    private async Task MyMethod()
    {
        textBlock.Text += "MyMethod start" + Environment.NewLine;
  
        await Task.Delay(3000); // here we are imitating the real work
  
        textBlock.Text += "MyMethod end" + Environment.NewLine;
    }

    public void StartProgress()
    {
        progress.IsIndeterminate = true;
        textBlock.Text += "StartProgress" + Environment.NewLine;
    }

    public void StopProgress()
    {
        progress.IsIndeterminate = false;
        textBlock.Text += "StopProgress" + Environment.NewLine;
    }

Edit

You can also wrap your existing synchronous method with Task.Run to run it asynchronously.

    private async Task MyMethod()
    {
        textBlock.Text += "MyMethod start" + Environment.NewLine;
        await Task.Run(() => NormalSubMethod1());
        textBlock.Text += "MyMethod end" + Environment.NewLine;
    }

    private void NormalSubMethod1()
    {
        long n = 0;
        for (var i = 0; i < 1e9; i++)
        {
            n++;
        }
    }

Upvotes: 2

Related Questions