0

I have a form where I use data from API. While getting data from server the form is blocked. I try to use async await and tasks but it does not help. The form is blocked anyway. Can you please explain how I can apply the async await in my app?

The code I use:

private void navigationTreeView_AfterSelect(object sender, TreeViewEventArgs e)
{
    Task task = SwitchToProjectsPanelAsync();
    task.Wait();
}

private async Task SwitchToProjectsPanelAsync()
{
    CurrentPanel.Visible = false;

    if (MyAllProjectsFlowLayoutPanel == null)
    {
        MyAllProjectsFlowLayoutPanel = new MyAllProjectsFlowLayoutPanel(this);
        MyAllProjectsFlowLayoutPanel.SuspendLayout();
        this.Controls.Add(MyAllProjectsFlowLayoutPanel);
        MyAllProjectsFlowLayoutPanel.AllProjects = _controller.GetProjectsList();

        MyAllProjectsFlowLayoutPanel.ShowProjectsList();
        CurrentPanel = MyAllProjectsFlowLayoutPanel;
        CurrentPanel.Visible = true;
        MyAllProjectsFlowLayoutPanel.ResumeLayout(false);
        MyAllProjectsFlowLayoutPanel.PerformLayout();
    }
    else
    {
        CurrentPanel = MyAllProjectsFlowLayoutPanel;
        CurrentPanel.Visible = true;
    }
}

Full code is on Git https://github.com/ViktorKuryshev/CRM

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • 2
    Instead of `task.Wait` you need to `await task` and let your event handler be an `async void`. – JSteward Jan 12 '18 at 20:03
  • 2
    Why is the `SwitchToProjectsPanelAsync` method async? it has no awaits? – Kevin Smith Jan 12 '18 at 20:04
  • Id suggest that you read about async and await. You are not using it correctly. – victor Jan 12 '18 at 20:05
  • 1
    You need to use `await`. That said, once you fix that, you're going to run into the problem that the `async` method you're awaiting isn't itself asynchronous, and so even using `await`, the thread will block. You'll want to look at posts like this: https://stackoverflow.com/q/25295479, https://stackoverflow.com/q/34151399, https://stackoverflow.com/q/25295166, https://stackoverflow.com/q/12786758, etc. or any number of [the rest you should've found had you bothered to search](https://stackoverflow.com/search?q=%5Bc%23%5D+async+block+ui) – Peter Duniho Jan 12 '18 at 20:10
  • I'm reading about it for two weeks already, but it did not helped me to understand how to apply it in my case. Now with your comments I got the it a little bit clearer, thank you. – Viktor Kuryshev Jan 13 '18 at 06:10

1 Answers1

1

The reason is simple: your first thread is blocked by waiting for the task you create:

            Task task = SwitchToProjectsPanelAsync();
            task.Wait(); // this is a blocking call

Instead, you should use await-based syntax:

private async void navigationTreeView_AfterSelect(object sender, TreeViewEventArgs e)
{
    await SwitchToProjectsPanelAsync();
}

Another point to pay attention is "what is the longest part in awaitable code?". I suspect you have to turn "_controller.GetProjectsList()" into async/await too as it can put you into troubles too (rule of thumb: do not touch UI from other threads! and you do so in your SwitchToProjectsPanelAsync).

P.S. Beware of "async void" combination that appears at this method signature. Naturally, you should avoid it as much as possible and use "async Task" or "async Task". Otherwise, exception info could not be passed right way. See this nice post https://haacked.com/archive/2014/11/11/async-void-methods

Yury Schkatula
  • 5,291
  • 2
  • 18
  • 42