使方法异步

时间:2013-04-08 20:44:51

标签: c# async-await bing-api

我有一个调用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;
        }

问题在于我不确定该代码中有什么等待。

5 个答案:

答案 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)));

}

在这种特殊情况下,除了创建任务之外不需要执行任何操作,根本不需要asyncawait,您只需返回构造的任务即可。如果你想在得到结果后做某事,你可以改为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没有像其他人所说的那样正确实施。