我有一个客户端应用程序,通过建立与服务器的长实时HTTP连接来实时监控更改。
在ASP.NET WebAPI中,服务器可以使用PushStreamContent
来保持连接很长时间,并在有更新后发送响应。
但在ServiceStack中,似乎没有类似的东西。
我查看了Different ways of returning an ImageStream的示例代码
IStreamWriter.WriteTo
方法只调用一次,我不能使用async
IO操作来避免阻塞服务器线程。
有没有办法异步向客户端发送渐进式响应?
这是WebAPI中执行作业的示例代码
public static async Task Monitor(Stream stream, HttpContent httpContent, TransportContext transportContext)
{
ConcurrentQueue<SessionChangeEvent> queue = new ConcurrentQueue<SessionChangeEvent>();
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
Action<SessionChangeEvent> callback = (evt) =>
{
queue.Enqueue(evt);
tcs.TrySetResult(null);
};
OnSessionChanged += callback;
try
{
using (StreamWriter sw = new StreamWriter(stream, new UTF8Encoding(false)))
{
await sw.WriteLineAsync(string.Empty);
await sw.FlushAsync();
await stream.FlushAsync();
for (; ; )
{
Task task = tcs.Task;
await Task.WhenAny(task, Task.Delay(15000));
if (task.Status == TaskStatus.RanToCompletion)
{
tcs = new TaskCompletionSource<object>();
SessionChangeEvent e;
while (queue.TryDequeue(out e))
{
string json = JsonConvert.SerializeObject(e);
await sw.WriteLineAsync(json);
}
task.Dispose();
}
else
{
// write an empty line to keep the connection alive
await sw.WriteLineAsync(string.Empty);
}
await sw.FlushAsync();
await stream.FlushAsync();
}
}
}
catch (CommunicationException ce)
{
}
finally
{
OnSessionChanged -= callback;
}
}
答案 0 :(得分:1)
看看example。如果我理解你,这就是你要找的。 p>
答案 1 :(得分:1)
写入长时间运行的连接正是Server Events的作用。您可以查看ServerEventsHandler或ServerEventsHeartbeatHandler的实施情况,看看它是否已在ServiceStack中实施。
基本上它只使用自定义的ASP.NET IHttpAsyncHandler,它可以在ServiceStack's Request Pipeline的开头注册:
appHost.RawHttpHandlers.Add(req => req.PathInfo.EndsWith("/my-stream")
? new MyStreamHttpHandler()
: null);
MyStreamHttpHandler是自定义HttpAsyncTaskHandler,例如:
public class MyStreamHttpHandler : HttpAsyncTaskHandler
{
public override bool RunAsAsync() { return true; }
public override Task ProcessRequestAsync(
IRequest req, IResponse res, string operationName)
{
//Write any custom request filters and registered headers
if (HostContext.ApplyCustomHandlerRequestFilters(req, res))
return EmptyTask;
res.ApplyGlobalResponseHeaders();
//Write to response output stream here, either by:
res.OuputStream.Write(...);
//or if need access to write to underlying ASP.NET Response
var aspRes = (HttpResponseBase)res.OriginalResponse;
aspRes.OutputStream...
//After you've finished end the request with
res.EndHttpHandlerRequest(skipHeaders: true);
return EmptyTask;
}
}
开头的ApplyCustomHandlerRequestFilters()
和ApplyGlobalResponseHeaders()
为其他插件提供了验证/终止请求或添加任何HTTP标头(例如CorsFeature)的机会。