2016-03-11 3 views
0

Предисловие: Я любитель, так что простите мое невежество, пожалуйста ;-) Я пытаюсь выполнить веб-многофункциональную задачу (решение для онлайн-астрометрии), которая находится в отдельном классе из моего главного окна. Я хотел бы сделать это в фоновом режиме, чтобы сохранить основное окно активным (для регистрации сообщений в прокрутке LogTextBox).
В моем главном окне я называю это:Запустить HttpClient PostAsync в другом классе из MainWindow Background worker?

public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
       Astrometry ast = new Astrometry(); 
       ast.OnlineSolve(GlobalVariables.SolveImage); 
     } 

И в астрометрии классе он останавливается на ожидании httpClient.PostAsync (... возвращается в главное окно и ничего не происходит

class Astrometry 
    { 

public void OnlineSolve(string image) 
     { 
      GetSession(apikey); 
     } 

private async void GetSession(string apikey) 
      { 
      ...misc code 
       using (var httpClient = new HttpClient()) 
        { 
         httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 
         HttpContent contentPost = new StringContent(input, Encoding.UTF8, "application/x-www-form-urlencoded"); 

         using (var response = await httpClient.PostAsync(baseAddress, contentPost)) 
         { 
          string responseData = await response.Content.ReadAsStringAsync(); 
           ...more stuff 
       } 
       } 

Я задаюсь вопросом, невозможно ли это сделать так ... Заранее благодарен

ответ

0

При использовании async/await вы должны всегда выполнять задачи.

public async Task OnlineSolve(string image) 
{ 
    await GetSession(apikey).ConfigureAwait(false); 
} 

private async Task GetSession(string apikey) 
{ 
     ...misc code 
    using (var httpClient = new HttpClient()) 
    { 
    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 
    HttpContent contentPost = new StringContent(input, Encoding.UTF8, "application/x-www-form-urlencoded"); 

    using (var response = await httpClient.PostAsync(baseAddress, contentPost).ConfigureAwait(false)) 
    { 
     string responseData = await response.Content.ReadAsStringAsync().ConfigureAwait(false); 
     ...more stuff 
    } 
    } 
} 

и снова в рабочем:

public async void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    Astrometry ast = new Astrometry(); 

    await ast.OnlineSolve(GlobalVariables.SolveImage); 
} 

Основное правило не нарушает AWAIT цепи. Как только вы его сломаете, вы потеряете отслеживание асинхронной операции, и вы потеряете свою операцию, чтобы ждать результата и обрабатывать любые ошибки.

Также обратите внимание, что, поскольку вы используете чистый асинхронный ввод-вывод, вам в действительности не нужно использовать фонового рабочего. Просто запустите асинхронный метод непосредственно из обработчика щелчка на кнопке или что-то еще, и все будет в порядке. Если вам нужно также работать с ЦП, Task.Run - достойный вариант. Я даже не уверен, что если рабочий стол обрабатывает сортировку await до правильной нити правильно (EDIT: И действительно, это не так, поэтому нет смысла использовать BackgroundWorker с await, это просто запутывает - просто используйте Task.Run для работы ЦП и await для асинхронного ввода-вывода).

Следует иметь в виду, что await в основном функционирует как магический return (аналогично yield return, если вы когда-либо использовали это). Как только выполнение достигнет await, которое ожидает выполнения задачи, которая не завершена, метод return s a Task (если возможно). Это тот момент, когда вызывающий получает обратное управление потоком - и если вы не используете await в вызывающем, это состояние, в котором работает работа, когда ваш вызывающий абонент продолжает выполнение. Иногда это желательно - например, при одновременном запуске нескольких задач. Обычно вы просто хотите, чтобы await все асинхронные методы немедленно.

+0

Спасибо! отлично работал, и я принял ваш совет и устранил фонового работника. – ksipp01

+0

@ Luaan: FYI, фоновой рабочий выйдет с первого уступчивого 'ожидания '. «DoWork» возобновляется в потоке пула потоков. Я нахожу это поведение запутанным (т. Е. Завершено увольняется «рано»), поэтому я рекомендую «Task.Run» над BGW, если вам это даже нужно. Который, конечно, вы не в этом случае. –

+0

@ StephenCleary Да, я вроде бы ожидал, что что-то подобное случится. Единственный способ, с которым он мог бы работать, был бы, если бы он использовал свой собственный контекст синхронизации, который был бы беспредметным * без * ожиданий. Я добавлю это к ответу. – Luaan

Смежные вопросы