簡體   English   中英

如何創建一個迭代器,該迭代器將在C#中產生HTTP響應主體的行?

[英]How to create an iterator that will yield lines of an HTTP response body in C#?

我最近的是

public async Task<IEnumerable<dynamic>> GetResults(string id, int n) {
    var client = new HttpClient();
    client.DefaultRequestHeaders.Add("Authorization", "Token " + token);
    Stream results = await client.GetStreamAsync(baseurl + id + "/results");

    StreamReader sr = new StreamReader(results);
    while(!sr.EndOfStream) {
        string line = await sr.ReadLineAsync();
        yield return Json.Decode(line);
    }
}

但是它說它不能是迭代器塊,因為System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<dynamic>>不是迭代器接口類型。

但是,我找不到沒有異步方法的流(我只能找到GetStreamAsync,沒有GetStream的定義)來獲取流,這迫使我具有異步方法,這迫使我返回Task。

為了流式傳輸響應,您必須手動寫入響應流。 您可以使用PushStreamContent ,並傳遞一個委托,該委托在准備好發送輸出流時立即將一行寫入輸出流:

public HttpResponseMessage GetResults(string id, int n) {
    var client = new HttpClient();
    client.DefaultRequestHeaders.Add("Authorization", "Token " + token);
    Stream results = await client.GetStreamAsync(baseurl + id + "/results");

    response.Content = new PushStreamContent(
        async (outputStream, httpContent, transportContext) => {
            using(outputStream)
            {
                StreamReader sr = new StreamReader(results);
                while(!sr.EndOfStream)
                {
                    string line = await sr.ReadLineAsync();
                    var decoded = Json.Decode(line);

                    //convert to byte array
                    byte[] buffer = //...

                    await outputStream.WriteAsync(buffer, 0, buffer.Length);
                }
            }
    });
}

有關更多詳細信息,請參見ASP.NET WebApi中的異步流


舊答案

正如編譯器所說,您需要返回IEnumerableIEnumerator

如果返回Task<IEnumerable<T>> ,客戶端將如何處理它? foreach在可枚舉上調用MoveNext() -相反,它將不得不調用await MoveNext IEnumerableTask<IEnumerable>不可互換。

您必須先收集結果,然后才能將枚舉數返回給客戶端。

public async Task<IEnumerable<dynamic>> GetResults(string id, int n) {

    //...

    StreamReader sr = new StreamReader(results);
    List<string> results = new List<string>();
    while(!sr.EndOfStream) {
        string line = await sr.ReadLineAsync();
        results.Add(line);
    }

    return results;
}

可以使用WebRequest類並按照該頁面上的示例進行管理:

public IEnumerable<dynamic> GetResults(string id, int n) {

    WebRequest request = WebRequest.Create(baseurl + id + "/results");
    request.Headers.Add("Authorization", "Token " + token);
    WebResponse response = request.GetResponse();
    Stream responseStream = response.GetResponseStream();

    StreamReader sr = new StreamReader(responseStream);
    while(!sr.EndOfStream) {
        string line = sr.ReadLine();
        yield return Json.Decode(line);
    }
}

WebResponse具有GetResponseStream ,而HttpClient僅具有GetStreamAsync 這使我不必等待,也不需要異步方法。

暫無
暫無

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

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