1

我有一个调用 Bing Api 的方法。

IEnumerable<WebResult> Search(string query)

我想让这个异步,这样如果我对它进行多次调用,每个调用都是独立的。因此,按照此处的建议,我将签名更改为

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;
        }

问题是我不确定在这段代码中要等待什么。

4

5 回答 5

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;
}
于 2013-04-08T21:00:04.793 回答
4

我对 Bing API 不是很熟悉,但是如果 API 不包含异步方法,您可以通过将调用包装在 started 中来实现异步Taskasync修饰符不会使您的方法自动异步,它只允许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 的回答在那里更详细。

于 2013-04-08T20:53:26.417 回答
0

根据 MSDN

通常,由 async 关键字修改的方法至少包含一个 await 表达式或语句。该方法同步运行,直到它到达第一个等待表达式,此时它被挂起,直到等待的任务完成。同时,控制权返回给方法的调用者。如果该方法不包含等待表达式或语句,则它会同步执行。编译器警告会提醒您注意任何不包含 await 的异步方法,因为这种情况可能表示错误。有关详细信息,请参阅编译器警告(级别 1)CS4014。

编辑:我想我会添加到这个,但它已经在这篇文章的评论部分。标记为 的方法在遇到关键字async之前实际上不会异步运行。await

于 2013-04-08T20:52:15.300 回答
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;
}
于 2017-09-03T04:27:46.263 回答
-1

该警告只是告诉您,无论您在哪里调用 SearchAsynch,它都需要在它之前等待。

var result = await SearchAsynch(query);

但是,SearchAsynch 没有像其他人所说的那样正确实现。

于 2013-04-08T20:50:30.173 回答