简体   繁体   中英

Task not working if background method needs UI: The calling thread must be STA, because many UI components require this

I have one Async method which performs different operations.

 public async void OnClickPublish( )
        {

            Loader loader = new Loader();
            loader.Show();
            await Task.Run(() => PublishSlides(loader));
        }


 private async Task PublishSlides(Loader loader)
        {

        await loader.Dispatcher.Invoke(async () =>
         { 

            loader.LoaderMessage("Opration 1 start..");
            List<SlideProperties> DBList= await Task.Run(() => 
            objSlideImg.DBOpration()); //UI Not needed. work nice



           var cloudTask = SendToCloudAsync(DBList);  
           await cloudTask.ContinueWith(task =>
           {
             if (task.IsFaulted)
              {
                 loader.LoaderMessage(task.Exception.Message + " problem occur in cloud publish");
                  return;
              } 

              loader.ShowSuccess("broadcasting..");
            }, uiScheduler);

        } 
        }


    /*PROBLEM OCCUR IN THIS METHOD*/
      public async Task<bool> SendToCloudAsync(List<SlideProperties> DBList)
        {
            **DashboardUI dashboard= new DashboardUI();**  /* giving issue The calling thread must be STA, because many UI components require this.*/
            dashboard.ShowDashboard()
        }

So when I called the SendToCloudAsync() methods it will give the issue The calling thread must be STA, because many UI components require this. SendToCloudAsync() this method will show the dashboard of my APP.

I strongly recommend separating UI code from background code, and having the UI layer "drive" the business/background code.

Currently, OnClickPublish calls PublishSlides on a background thread ( Task.Run ), and then PublishSlides immediately jumps back to the UI thread ( Dispatcher.Invoke ) and runs its entire method body on the UI thread. This isn't accomplishing anything - just jumping back and forth across threads.

To properly divide UI from background thread code, there are two primary techniques and one less common technique.

The first primary technique is to use return values. Instead of having a method retrieve/calculate data and then update the UI with the data results, just have it retrieve/calculate data and return it. Then the calling thread can decide whether the retrieving/calculation should be on a background thread ( Task.Run ), and then place the data on the UI.

The second primary technique is to use progress updates. Instead of having a "work" method reach into the UI and update the progress directly, it should use IProgress<T> to report progress. Then the calling method can decide whether the "work" should be run on a background thread ( Task.Run ), and it can pass a progress implementation (eg, Progress<T> ) that performs progress updates on the UI thread.

The less common technique is to proactively update the UI from a continuously running background operation. I recommend using SynchronizationContext for that, but because the code is more complex and doesn't apply to this question I'll just stop there.

Here's one example of what your code could look like using return values and await . The exact details will depend on the details of the rest of your code:

public async void OnClickPublish()
{
  Loader loader = new Loader();
  loader.Show();
  PublishSlides(loader);
}

private async Task PublishSlides(Loader loader)
{
  loader.LoaderMessage("Opration 1 start..");
  List<SlideProperties> DBList = await Task.Run(() => objSlideImg.DBOpration());

  try
  {
    await SendToCloudAsync(DBList);
    loader.ShowSuccess("broadcasting..");
  }
  catch (Exception ex)
  {
    loader.LoaderMessage(ex.Message + " problem occur in cloud publish");
  } 

  DashboardUI dashboard = new DashboardUI();
  dashboard.ShowDashboard();
}

public async Task<bool> SendToCloudAsync(List<SlideProperties> DBList)
{
  ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM