相关问题
插件开发中流式处理的现代化改造
描述你希望的解决方案
描述你希望的解决方案
在 IHttpService 接口中新增一个支持 IAsyncEnumerable 的流式 POST 方法:
/// <summary>
/// 流式Post请求(IAsyncEnumerable模式)
/// </summary>
/// <param name="url">请求URL</param>
/// <param name="content">请求体</param>
/// <param name="options">请求选项</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>异步流,每项是一行SSE数据</returns>
IAsyncEnumerable<string> StreamPostAsyncEnumerable(
string url,
object content,
Options? options = null,
CancellationToken cancellationToken = default);
HttpService 实现示例:
public async IAsyncEnumerable<string> StreamPostAsyncEnumerable(
string url,
object content,
Options? options = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
using var client = _httpClientFactory.CreateClient(Constant.HttpClientName);
// ... 配置 ...
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
using var reader = new StreamReader(stream);
string? line;
while (!cancellationToken.IsCancellationRequested && (line = await reader.ReadLineAsync(cancellationToken)) != null)
{
if (!string.IsNullOrEmpty(line))
{
yield return line;
}
}
}
优点:
纯增量添加,不影响现有接口
向后兼容,旧插件无需修改
新插件可选择更现代的 IAsyncEnumerable 模式
便于在插件中实现 await foreach 遍历
描述你所考虑的替代方案
- 保持现有回调模式:继续使用 Action 回调,但这种方式在异步上下文中不够直观,且难以实现早期取消和异常处理。
- 自定义 HttpService 封装:在插件内部自行实现 HttpClient 流式处理,但会重复 HttpService 的配置和错误处理逻辑,且无法复用主程序的 HttpClientFactory 管理。
- 修改现有 StreamPostAsync 签名:破坏性太大,会强制所有插件修改。
选择 IAsyncEnumerable 的原因:
- 官方推荐的流式处理方式
- 天然支持 CancellationToken 和异常处理
- 与现有方法共存,可选使用
- 代码更简洁易读
我确认已查询历史issues
相关问题
插件开发中流式处理的现代化改造
描述你希望的解决方案
描述你希望的解决方案
在 IHttpService 接口中新增一个支持 IAsyncEnumerable 的流式 POST 方法:
HttpService 实现示例:
优点:
纯增量添加,不影响现有接口
向后兼容,旧插件无需修改
新插件可选择更现代的 IAsyncEnumerable 模式
便于在插件中实现 await foreach 遍历
描述你所考虑的替代方案
选择 IAsyncEnumerable 的原因:
我确认已查询历史issues