我有一个调用Bing Api的方法。
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;
}
问题在于我不确定该代码中有什么等待。
答案 0 :(得分: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;
}
答案 1 :(得分: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
从异步方法对创建任务。 Servy的答案在那里更详细。
答案 2 :(得分:0)
每个MSDN
编辑:我想我会添加这个,但它已经在这篇文章的评论部分。标记为通常,由async关键字修改的方法至少包含 一个等待表达 或声明。该方法同步运行,直到它到达第一个await表达式, 此时它将暂停,直到等待的任务完成。同时, 控制权返回给方法的调用者。如果方法不包含await 表达式或语句,然后它同步执行。编译器警告提醒您 任何不包含等待的异步方法,因为这种情况可能表示错误。 有关更多信息,请参阅编译器警告(级别1)CS4014。
async
的方法在点击await
关键字之前实际上不会执行异步。
答案 3 :(得分:0)
这是在独立项目中使用async的示例。
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;
}
答案 4 :(得分:-1)
警告只是告诉你,无论你在哪里调用SearchAsynch,它都需要等待它。
var result = await SearchAsynch(query);
但是,SearchAsynch没有像其他人所说的那样正确实施。