2013-11-12 4 views
0

Я спросил об этом раньше, но ни один из ответов не закончился. Итак, у меня есть класс, который делает веб-запрос для получения строки данных и метод в этом классе, который вызывает метод для этого, а затем возвращает строковое значение.C# Веб-запрос вызывает сбой

У меня есть класс MainPage, класс City (WebRequest возвращает строку JSON, и этот класс анализирует ее и сохраняет данные), и у меня есть класс WebRetrieval.

В MainPage у меня есть это:

private void City_GoButton_Click(object sender, RoutedEventArgs e) 
{ 
    City cityObject = new City(); 
    WebRetrieval wr = new WebRetrieval(); 

    string jsonString; 
    string formattedString; 

    if (String.IsNullOrWhiteSpace(CityID_Textbox.Text)) 
    { 
     MessageDialog md = new MessageDialog("Please enter in a number"); 
     md.ShowAsync(); 
    } 
    else 
    { 
     long cityNum = Convert.ToInt64(CityID_Textbox.Text); 
     string url = "http://honey.computing.dcu.ie/city/city.php?id=" + cityNum; 

     jsonString = wr.GetResult(url); 
     formattedString = cityObject.ReturnFormattedString(jsonString); 
    } 
} 

А в классе Web Retrieval я это:

async public void GetInformation(string url) 
{ 
    var client = new HttpClient(); 
    var response = await client.GetAsync(new Uri(url)); 
    result = await response.Content.ReadAsStringAsync(); 
} 

public string GetResult(string url) 
{ 
    GetInformation(url); 
    return result; 
} 

И что странно, что, в классе WebRetrieval, внутри GetInformation метод, когда он пытается выполнить ответ, программа переходит в мой класс City и терпит неудачу, потому что полученная строка равна null. Он никогда не попадает в результирующую строку внутри метода GetInformation.

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

Надеюсь, кто-то может мне помочь. Приветствия

ответ

2

Вы должны избегать async void. Я подробно объясняю «почему» в моей статье MSDN Best Practices in Asynchronous Programming.

void - очень неестественный тип возврата для async методов. Его следует использовать только при записи обработчика событий async (который должен вернуть void).

Таким образом, преобразование всех async void методы async Taskfollowing the naming convention):

async public Task GetInformationAsync(string url) 
{ 
    var client = new HttpClient(); 
    var response = await client.GetAsync(new Uri(url)); 
    result = await response.Content.ReadAsStringAsync(); 
} 

Эти задачи должны быть await изд:

public string GetResult(string url) 
{ 
    await GetInformationAsync(url); 
    return result; 
} 

Но тогда компилятор будет жаловаться, что если вы используете await, вы должны сделать свой метод async, поэтому мы делаем:

public async Task<string> GetResultAsync(string url) 
{ 
    await GetInformationAsync(url); 
    return result; 
} 

И await, что тоже:

private void City_GoButton_Click(object sender, RoutedEventArgs e) 
{ 
    ... 
    jsonString = await wr.GetResultAsync(url); 
    formattedString = cityObject.ReturnFormattedString(jsonString); 
} 

Еще раз, компилятор жалуется, так что мы это исправить, сделав метод вызова async (обычно, мы бы сделать его async Task, но это должно быть, потому что async void это обработчик событий):

private async void City_GoButton_Click(object sender, RoutedEventArgs e) 
{ 
    ... 
    jsonString = await wr.GetResultAsync(url); 
    formattedString = cityObject.ReturnFormattedString(jsonString); 
} 

И все готово.

Вы можете найти мой async intro полезный.

+0

Ничего себе, что отличный ответ. Это сработало для меня и объяснило это очень хорошо! Большое вам спасибо за то, что нашли время, чтобы объяснить этого человека! – AndyOHart

1

Если я правильно понять это, GetResult звонит GetInformation, который является async метод. В принципе, внутренности GetResult не нужно ждать завершения звонка GetInformation, чтобы закончить. У вас есть проблема с синхронизацией.

некоторые возможные решения, это может быть либо отметки GetResult в async, и он ждет GetInformation, или иметь GetInformation возвращают значение, которое затем можно заставить выполнить путем вызова .Result на задаче.

+0

Да, я пробовал что-то похожее на это, но я не знаю, как вернуть значение в асинхронном методе? Если я верну задание , я не могу преобразовать его в jsonString = wr.GetResult (url); в классе MainPage. В любом случае? – AndyOHart

+1

Методы Async, возвращающие значения, должны иметь возвращаемый тип 'Task'. Например, если у вас есть метод с сигнатурой 'async public Task GetInformation (...)', вы можете просто вернуть строку. В коде вашего потребителя вы можете написать «Задача task = GetInformation();», а затем, чтобы обеспечить завершение вызова метода async, вы должны написать «string result = task.Result;» Это также может помочь: http: //msdn.microsoft.com/en-us/library/vstudio/hh524395.aspx#BKMK_TaskTReturnType – matt

+0

@ Спасибо за этого человека, я, наконец, получил его для компиляции. Однако код, кажется, просто останавливается в разделе ответа в GetInformation. Если я установил контрольную точку перед ней и прохожу через нее, когда я попытаюсь сделать шаг после var response = wait client.GetAsync (новый Uri (url)), мой код просто остановится, и он возвращает меня в приложение. Кажется, код просто не работает, чтобы закончить еще – AndyOHart

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