2013-04-08 2 views
1

У меня есть метод, который вызывает Bing Api.Выполнение метода asynch

IEnumerable<WebResult> Search(string query) 

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

async Task<IEnumerable<WebResult>> SearchAsynch(string query) 

Но я получаю предупреждение

This async method lacks 'await' operators and will run synchronously... 

Я хочу, чтобы весь метод был асинхронным (по крайней мере, как я думаю, что он должен работать). Как мне это сделать? Вот мой код

public async Task<IEnumerable<WebResult>> SearchAsynch(string query) 
     { 
      if (query == null) 
      { 
       throw new ArgumentNullException("query cannot be null"); 
      } 

      DataServiceQuery<WebResult> webQuery = _bingContainer.Web(query, null, null, null, null, null, null, null); 
      IEnumerable<WebResult> webResults = webQuery.Execute(); 
      return webResults; 
     } 

Проблема в том, что я не уверен, чего ждать в этом коде.

+1

Возможно, статья [this] (http://msdn.microsoft.com/en-us/library/dd756367.aspx) будет полезной? – nkvu

+0

+1 за полезный намек. Благодарю. –

ответ

6

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

В этом случае класс DataServiceQuery уже предоставляет способ асинхронного выполнения запроса. К сожалению, он использует старую асинхронную модель, не новый Task на основе модели, так что вам нужно использовать Task.Factory.FromAsync, чтобы перевести его:

public Task<IEnumerable<WebResult>> SearchAsynch(string query) 
{ 
    DataServiceQuery<WebResult> webQuery = _bingContainer.Web(query, null, null, null, null, null, null, null); 

    return Task.Factory.FromAsync(webQuery.BeginExecute(null, null) 
     , asyncResult => webQuery.EndExecute(asyncResult))); 

} 

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

public async Task<IEnumerable<WebResult>> SearchAsynch(string query) 
{ 
    DataServiceQuery<WebResult> webQuery = _bingContainer.Web(query, null, null, null, null, null, null, null); 
    var results = await Task.Factory.FromAsync(webQuery.BeginExecute(null, null) 
      , asyncResult=> webQuery.EndExecute(asyncResult)); 
    Console.WriteLine("Hi there"); 
    return results; 
} 
+0

С помощью этого метода я использую ключевое слово async при вызове SearchAsync? –

+0

@SachinKainth Вы можете использовать его или нет; это полностью зависит от того, хотите вы или нет, или же это подходит в контексте. Вы, конечно, не имеете *, но можете. – Servy

-1

Предупреждение просто говорит вам, что везде, где вы звоните в SearchAsynch, он должен дождаться этого.

var result = await SearchAsynch(query);

Однако SearchAsynch не должным образом реализованы как другие заявили.

+0

Ну, нет, это не работает, потому что я получил ошибку «Оператор ожидания может использоваться только в методе или лямбда, отмеченном модификатором async» –

+1

Ему нужно закончить правильную реализацию «SearchAsynch» (вот что это за вопрос: с просьбой о помощи), прежде чем он сможет «подождать». – Servy

+0

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

0

За MSDN

Как правило, метод модифицируется асинхронном ключевым словом содержит по крайней мере один ждет выражение или утверждение. Метод работает синхронно, пока не достигнет первого ожидающего выражения , после чего он будет приостановлен до завершения ожидаемой задачи. Тем временем, вызывающему абоненту метода возвращается . Если метод не содержит выражения или выражения , то он выполняется синхронно. Предупреждение о компиляторе предупреждает вас об любых методах async, которые не содержат ожидания, потому что эта ситуация может указывать на ошибку. Дополнительную информацию см. В разделе Предупреждение о компиляторе (уровень 1) CS4014.

EDIT: Я решил, что добавлю к этому, но это уже в разделе комментариев этого сообщения. Метод, отмеченный async, фактически не запускает асинхронный пока не достигнет ключевого слова await.

+0

Спасибо, это я знал, но моя проблема в том, что я не знаю, чего ждать в моем коде. –

+0

@SachinKainth Ключевое слово ожидания должно применяться к вашей строке webQuery.Execute(), а затем вы возвращаете свои данные. Ключевое слово ожидания - это фактическое начало операции async. До этого он выполняется синхронно. – Justin

4

Я не очень хорошо знаком с Bing API, но если API не содержит асинхронных методов, вы можете сделать один асинхронный процесс, завернув вызовы в начальный Task. async модификатор не делает ваш метод автоматически асинхронным, он позволяет только await другим асинхронным методам.

Таким образом, в вашем случае, вероятно, было бы проще всего:

public Task<IEnumerable<WebResult>> SearchAsync(string query) 
    { 
     if (query == null) 
     { 
      throw new ArgumentNullException("query cannot be null"); 
     } 

     return Task.Run(() => 
      { 
       DataServiceQuery<WebResult> webQuery = _bingContainer.Web(query, null, null, null, null, null, null, null); 
       return webQuery.Execute(); 
      } 
    } 

Затем вы можете await этот метод в другой метод, помеченный как async:

var result = await SearchAsync("yourQuery"); 

Если Bing API имеет асинхронные пары методов Begin/End, вы можете использовать Task.Factory.FromAsync для создания задачи из пар асинхронных методов. Ответ Сервиса здесь более подробно.

+0

Проблема заключается в том, что я буду тестировать этот метод, и эти методы не будут помечены как async. –

+1

Если вы тестируете устройство и не хотите играть с контекстами синхронизации, вы можете сделать блокировку ожидания. 'var taskResult = SearchAsync (" query "); Task.Wait (taskResult); '. Затем вы можете получить доступ к результату с помощью 'taskResult.Result'. Это * должно, вероятно, работать ... –

+0

Плюс я получаю еще одну ошибку: «Поскольку это метод async, выражение return должно иметь тип« System.Collections.Generic.IEnumerable », а не« Task < System.Collections.Generic.IEnumerable > '" –

0

Это является примером использования асинхр в одиночку проекта стенда.

private async void button2_Click(object sender, EventArgs e) 
{ 
    DataTable dtMessages = await getMessages2(string sqlConn2, nMessage); 
} 
public async Task<DataTable> getMessages2(string sqlConn, int n) 
{ 
    //create your query and command 
    var o = await cmd2.ExecuteReaderAsync(); 
    DataTable dtMessages = o; 
    return dtMessages; 
} 
Смежные вопросы