C# 使方法异步

C# 使方法异步,c#,async-await,bing-api,C#,Async Await,Bing Api,我有一个调用Bing Api的方法 IEnumerable<WebResult> Search(string query) 我希望整个方法是异步的,至少我认为它应该是异步的。我该怎么做?这是我的密码 public async Task<IEnumerable<WebResult>> SearchAsynch(string query) { if (query == null) {

我有一个调用Bing Api的方法

IEnumerable<WebResult> Search(string query)
我希望整个方法是异步的,至少我认为它应该是异步的。我该怎么做?这是我的密码

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

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

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

var result=await SearchAsynchquery


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

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

var result=await SearchAsynchquery

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

根据MSDN

通常,由async关键字修改的方法至少包含 等待表情 或声明。该方法同步运行,直到到达第一个等待表达式, 此时将暂停,直到等待的任务完成。同时,, 控件返回给方法的调用方。如果该方法不包含等待 表达式或语句,然后同步执行。编译器警告提醒您 任何不包含的异步方法都将等待,因为这种情况可能表明存在错误。 有关更多信息,请参阅编译器警告级别1 CS4014

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

Per MSDN

通常,由async关键字修改的方法至少包含 等待表情 或声明。该方法同步运行,直到到达第一个等待表达式, 此时将暂停,直到等待的任务完成。同时,, 控件返回给方法的调用方。如果该方法不包含等待 表达式或语句,然后同步执行。编译器警告提醒您 任何不包含的异步方法都将等待,因为这种情况可能表明存在错误。 有关更多信息,请参阅编译器警告级别1 CS4014


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

我对Bing API不是很熟悉,但是如果API不包含async方法,可以通过将调用包装到已启动的任务中来实现一个async。async修饰符不会使您的方法自动异步,它只允许在内部等待其他异步方法

因此,在您的情况下,可能最容易:

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

如果Bing API具有异步方法对Begin/End,则可以使用Task.Factory.fromsync从异步方法对创建任务。Servy的回答更详细。

我对Bing API不是很熟悉,但如果API不包含异步方法,可以通过将调用包装到已启动的任务中来实现异步。async修饰符不会使您的方法自动异步,它只允许在内部等待其他异步方法

因此,在您的情况下,可能最容易:

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();
            }
    }
如果Bing API具有异步方法对Begin/End,则可以使用Task.Factory.fromsync从异步方法对创建任务。Servy的回答更详细。

async关键字不会创建新的异步操作,它只是一种更容易为任务(即已经存在的异步操作)配置延续的方法

在本例中,DataServiceQuery类已经提供了异步执行查询的方法。不幸的是,它使用的是旧的异步模型,而不是新的基于任务的模型,因此您需要使用Task.Factory.fromsync来转换它:

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关键字不会创建新的异步操作,它只是一种更容易为任务(即已经存在的异步操作)配置延续的方法

在本例中,DataServiceQuery类已经提供了异步执行查询的方法。不幸的是,它使用的是旧的异步模型,而不是新的基于任务的模型,因此您需要使用Task.Factory.fromsync来转换它:

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

}

这是一个在独立项目中使用异步的示例

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

这是一个在独立项目中使用异步的示例

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

也许这篇文章会有帮助?+1提供有用的提示。谢谢。也许这篇文章会有所帮助?+1提供有用的提示。谢谢,嗯,不,这不起作用,因为我得到了一个错误,wait运算符只能用于标记有async修饰符的方法或lambda。他需要正确地实现SearchAsync,这是这个问题在他可以等待它之前要求帮助的。警告特别指出,他正在做的事情将同步运行直到等待关键字

使用。因此,即使他正确地实现了它,并且缺少wait关键字,它也不会是异步的。不值得投反对票。@KyleC我想你还是没抓住重点。如果他正确地实现了该方法,警告就会消失,因为它是关于方法内部的代码,而不是调用该方法的代码。如何调用这个方法完全是另一个问题,不,这不起作用,因为我得到了一个错误,wait运算符只能用于标记有async修饰符的方法或lambda。他需要正确地实现SearchAsync,这是这个问题在他可以等待它之前要求帮助的。警告特别指出,他正在做的事情将同步运行直到使用wait关键字。因此,即使他正确地实现了它,并且缺少wait关键字,它也不会是异步的。不值得投反对票。@KyleC我想你还是没抓住重点。如果他正确地实现了该方法,警告就会消失,因为它是关于方法内部的代码,而不是调用该方法的代码。如何调用该方法完全是另一个问题。谢谢,我知道这一点,但我的问题是我不知道在我的代码中等待什么。@SachinKainth wait关键字应应用于您的webQuery。执行行,然后返回数据。wait关键字是异步操作的实际开始。在此之前,它是同步执行的。谢谢,我知道这一点,但我的问题是我不知道在我的代码中等待什么。@SachinKainth wait关键字应该应用于您的webQuery。执行行,然后返回数据。wait关键字是异步操作的实际开始。在此之前,它是同步执行的。如果您正在进行单元测试,并且不想使用同步上下文,则可以执行阻塞等待。var taskResult=SearchAsyncquery;Task.WaittaskResult;。然后可以通过taskResult.result访问结果。这可能会起作用……这不是真正的异步。您的线程池线程浪费了所有的时间,在等待IO时什么也不做,而只是使用异步查询操作。@SachinKainth您需要从方法签名中删除异步,就像这里所做的那样。@Servy当然,但是如果您在Bing端缺少真正的异步API,我想这是你能做的最好的了…@Trustme-I'maDoctor,但他并不缺少真正的异步API。如果您正在进行单元测试,并且不想使用同步上下文,那么可以执行阻塞等待。var taskResult=SearchAsyncquery;Task.WaittaskResult;。然后可以通过taskResult.result访问结果。这可能会起作用……这不是真正的异步。您的线程池线程浪费了所有的时间,在等待IO时什么也不做,而只是使用异步查询操作。@SachinKainth您需要从方法签名中删除异步,就像这里所做的那样。@Servy当然,但是如果您在Bing端缺少真正的异步API,我想这是你能做的最好的了…@Trustme-I'maDoctor,但他并不缺少真正的异步API。使用此方法调用SearchAsync时是否使用async关键字?@SachinKainth您是否可以使用它;这完全取决于你是否愿意,或者它在上下文中是否合适。您当然不必这样做,但您可以这样做。使用此方法调用SearchAsync时是否使用async关键字?@SachinKainth您可以使用它,也可以不使用它;这完全取决于你是否愿意,或者它在上下文中是否合适。你当然不必,但你有能力。
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;
}