0

I've a button in my WPF application which function as follows

private void Button_Click(object sender, RoutedEventArgs e)
{
    loadingSpinner.Visibility = Visibility.Visible;
    DoSomeTask();    // Takes 3-4 seconds
}

My problem is the below code

loadingSpinner.Visibility = Visibility.Visible;

executes after DoSomeTask() execution is completed and all the UI related code is blocked which is written above it. I tried background workers, Parallel.Invoke and async Task but nothing worked. This just looked like a job of couple of minutes but it has been over a day and I'm not able to go past through it.

EDIT

If I try await like this

private async void Button_Click(object sender, RoutedEventArgs e)
{
    loadingSpinner.Visibility = Visibility.Visible;
    await Task.Run(() => DoSomeTask());    // Takes 3-4 seconds
}

The loadingSpinner becomes visible but code inside DoSomeTask() is never executed (which opens a webpage and performs some actions)

private void DoSomeTask()
{
    //... init variables

    driver.Navigate().GoToUrl("https://myurl.com");
    
    //.. some clicks and data filling
    driver.FindElement(By.Id("name")).SendKeys("Test");    
    driver.FindElement(By.Id("btn")).Click();
}
Vishal Afre
  • 1,013
  • 3
  • 12
  • 39
  • async is probably the way to go here. You said that it did not work - can you show us this implementation? – Klaus Gütter Jul 11 '20 at 08:53
  • https://social.msdn.microsoft.com/Forums/vstudio/en-US/8dfd0b0f-7926-4d37-85dd-96ddbac71ba3/wpf-how-to-show-progress-bar-on-button-click-to-show-operation-is-in-progress-till-the-process-is?forum=wpf – LDS Jul 11 '20 at 09:06
  • _"loadingSpinner.Visibility = Visibility.Visible; executes after DoSomeTask() execution is completed"_. This is not possible in this context. Since the instruction to change the visibility comes first, it executes first. Compiler don't skip code randomly or changes execution order randomly. Do you mean something different? [Asynchronous programming with async and await](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/#dont-block-await-instead). – BionicCode Jul 11 '20 at 09:33
  • You may have to modify the `DoSomeTask()` too. But this depends on how it is implemented or what exactly it is doing (what you didn't show!). – BionicCode Jul 11 '20 at 09:38
  • [Asynchronous programming](https://learn.microsoft.com/en-us/dotnet/csharp/async). – BionicCode Jul 11 '20 at 09:39
  • Added the code with await – Vishal Afre Jul 12 '20 at 05:03

1 Answers1

0

You have two options here. Either you make the DoSomeTask() an async Task and await it or you wrap it into a Task.Run():

private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    spinner.Visibility = Visibility.Visible;
    await DoSomeTask();
    spinner.Visibility = Visibility.Hidden;
}

private async Task DoSomeTask() => await Task.Delay(5000);

Or:

private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    spinner.Visibility = Visibility.Visible;
    await Task.Run(DoSomeTask);
    spinner.Visibility = Visibility.Hidden;
}

private void DoSomeTask() => Thread.Sleep(5000);
Florian H.
  • 89
  • 10
  • More precisely, the DoSomeTask method in the first example must be awaitable, but not necessarily async. `private Task DoSomeTask() => Task.Delay(5000);` would also work. – Clemens Jul 11 '20 at 10:28
  • 1
    A thread.sleep is almost always going to fail any code review nowadays. Rarely good practice. I'd prefer not to see one in an answer. – Andy Jul 11 '20 at 11:06
  • Actually in DoSomeTask, I'm loading a webpage in chrome browser through selenium and if I use await there, the spinner works fine but code inside DoSomeTask is never executed so I'm left with a blank chrome window – Vishal Afre Jul 12 '20 at 04:51
  • @Clemens you absolutely correct! – Florian H. Jul 12 '20 at 09:21
  • @VishalAfre That's a separate issue though, right? Are you setting UI elements in the Task? – Florian H. Jul 12 '20 at 09:21
  • No, I'm just executing selenium methods – Vishal Afre Jul 12 '20 at 09:30