簡體   English   中英

使方法異步

[英]Making a method asynch

我有一個叫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;
        }

問題是我不確定這段代碼要等待什么。

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

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

然后,您可以在其他標記為async方法中await該方法:

var result = await SearchAsync("yourQuery");

如果Bing API具有異步方法對Begin/End ,則可以使用Task.Factory.FromAsync從異步方法對創建任務。 Servy的答案在那里有更詳細的說明。

每個MSDN

通常,由async關鍵字修改的方法至少包含一個await表達式或語句。 該方法將同步運行,直到到達第一個await表達式為止,此時該方法將被掛起,直到完成等待的任務。 同時,控制權返回給方法的調用者。 如果該方法不包含await表達式或語句,則它將同步執行。 編譯器警告您任何不包含等待狀態的異步方法,因為這種情況可能表示錯誤,從而警告您。 有關更多信息,請參見編譯器警告(等級1)CS4014。

編輯:我想我會添加到這,但它已經在這篇文章的評論部分。 標記為async的方法只有在命中await關鍵字后才真正運行異步。

這是在獨立項目中使用異步的示例。

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

警告只是告訴您,無論您在哪里調用SearchAsynch,都需要等待它。

var result = await SearchAsynch(query);

但是,SearchAsynch沒有如其他人所述正確實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM