如何在c#中创建一个迭代器来生成HTTP响应体的行



最接近的是

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。

设法使用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。这允许我不必等待,也没有async方法

为了流式处理响应,您必须手动写入响应流。您可以使用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 MoveNextIEnumerableTask<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;
}

相关内容

  • 没有找到相关文章

最新更新