![](/img/trans.png)
[英]C#: yield return within a foreach fails - body cannot be an iterator block
[英]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中的異步流 。
舊答案
正如編譯器所說,您需要返回IEnumerable
或IEnumerator
。
如果返回Task<IEnumerable<T>>
,客戶端將如何處理它? foreach
在可枚舉上調用MoveNext()
-相反,它將不得不調用await MoveNext
。 IEnumerable
和Task<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.