Использование MessageBox, когда часть ожидающего имеет ConfigureAwait false - PullRequest
0 голосов
/ 28 июня 2018

Чтение Стивена Клири, беру , не блокируя асинхронный код Я пишу что-то вроде этого

public static async Task<JObject> GetJsonAsync(Uri uri)
{
   using (var client = new HttpClient())
   {
      var jsonString = await client.GetStringAsync(uri).ConfigureAwait(false);  
      return JObject.Parse(jsonString);
   }
}

public async void Button1_Click(...)
{
    var json = await GetJsonAsync(...);
    textBox1.Text=json;
}

пока все хорошо, я понимаю, что после ConfigureAwait метод продолжит работу в другом контексте после возврата GetStringAsync. но что делать, если я хочу использовать что-то вроде MessageBox (который является пользовательским интерфейсом), как это

public static async Task<JObject> GetJsonAsync(Uri uri)
{
   if(someValue<MAXVALUE)
   {
      using (var client = new HttpClient())
      {
         //var jsonString = await client.GetStringAsync(uri);  //starts the REST request
         var jsonString = await client.GetStringAsync(uri).ConfigureAwait(false);    
         return JObject.Parse(jsonString);
      }
   }
   else
   {
      MessageBox.Show("The parameter someValue is too big!");
   }
}

я могу это сделать?

Еще сложнее, как насчет этого?

public static async Task<JObject> GetJsonAsync(Uri uri)
{
   if(someValue<MAXVALUE)
   {
      try{
         using (var client = new HttpClient())
         {
            //var jsonString = await client.GetStringAsync(uri);  //starts the REST request
            var jsonString = await client.GetStringAsync(uri).ConfigureAwait(false);    
            return JObject.Parse(jsonString);
         }
      }
      catch(Exception ex)
      {
         MessageBox.Show("An Exception was raised!");
      }
   }
   else
   {
      MessageBox.Show("The parameter someValue is too big!");
   }
}

Могу ли я сделать это?

Теперь я думаю, что, возможно, все окна сообщений должны быть вызваны вне GetJsonAync как хороший дизайн, но мой вопрос в том, можно ли что-то сделать выше?

Ответы [ 2 ]

0 голосов
/ 28 июня 2018

Я бы не использовал окно сообщений, так как оно очень ограничено и датировано. Кроме того, всплывающие окна раздражают. Используйте свой собственный пользовательский элемент управления, который позволяет взаимодействовать с пользователем так, как вы этого хотите.

В контексте Winforms / WPF / (и я предполагаю, что UWP), только один поток может манипулировать UI. Другие потоки могут выдавать ему работу через очередь действий, которые в конечном итоге вызываются.

Эта архитектура не позволяет другим потокам постоянно тыкать в пользовательском интерфейсе, что может сделать UX очень неудобным (и небезопасным).

Единственный способ связаться с ним - рабочая очередь пользовательского интерфейса (в Winforms) - использовать метод экземпляра System.Windows.Form.Controls.BeginInvoke, который можно найти в каждой форме и элементе управления.

В вашем случае:

public async void Button1_Click(...)
{
    var json = await GetJsonAsync(...).ConfigureAwait(false);
    BeginInvoke(UpdateTextBox, json);
}

private void UpdateTextBox(string value)
{
  textBox1.Text=json;
}
0 голосов
/ 28 июня 2018

я могу это сделать? [используйте MessageBox]

Да, но в основном потому, что это не имеет ничего общего с асинхронностью / ожиданием или многопоточностью.
MessageBox.Show() является особенным, это статический метод и задокументирован как потокобезопасный.

Вы можете показать MessageBox из любого потока в любое время.

Так что, возможно, это был неправильный пример, но у вас есть MessageBox в заголовке.

public static async Task<JObject> GetJsonAsync(Uri uri)
{
   try{
     ...  // old context
     ... await client.GetStringAsync(uri).ConfigureAwait(false);
     ...  // new context
   }
   catch
   {
      // this might bomb
      someLabel.Text = "An Exception was raised!";
   }
}

В этом примере могут быть пути кода, где перехват выполняется по старому, и другие пути, где он запускается в новом контексте.

Итог: вы не знаете и должны принять наихудший случай.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...