我有一个 http 处理程序,它应该写入以输出一些文本。文本内容是异步检索的,所以我想像这样在 ProcessRequest 方法中写入响应流:
GetContent().ContinueWith(task =>
{
using (var stream = task.Result)
{
stream.WriteTo(context.Response.OutputStream);
}
});
但是,我得到一个带有堆栈跟踪的 NullReferenceException
in System.Web.HttpWriter.BufferData(Byte[] data, Int32 offset, Int32 size, Boolean needToCopyData)
in System.Web.HttpWriter.WriteFromStream(Byte[] data, Int32 offset, Int32 size)
in System.Web.HttpResponseStream.Write(Byte[] buffer, Int32 offset, Int32 count)
in System.IO.MemoryStream.WriteTo(Stream stream)
in SomeHandler.<>c__DisplayClass1.<ProcessRequest>b__0(Task`1 task) in SomeHandler.cs:line 33
in System.Threading.Tasks.ContinuationTaskFromResultTask`1.InnerInvoke()
in System.Threading.Tasks.Task.Execute()
如果我不使用 ContinueWith 并在 task.Wait() 之后写入响应 - 没有错误,但显然这不是解决方案。
var task = GetContent();
task.Wait();
using (var stream = task.Result)
{
stream.WriteTo(context.Response.OutputStream);
}
如何消除这个错误? (使用.net 4.0)
最佳答案
您需要实现IHttpAsyncHandler
。检查"Walkthrough: Creating an Asynchronous HTTP Handler" .
最重要的是,您可以使用 async/await
复制流(注意下面的 CopyAsync
)。为了能够在 VS2012+ 中使用 async/await
和目标 .NET 4.0,添加 Microsoft.Bcl.Async
打包到您的项目中。
这样,就不会不必要地阻塞任何线程。一个完整的例子(未经测试):
public partial class AsyncHandler : IHttpAsyncHandler
{
async Task CopyAsync(HttpContext context)
{
using (var stream = await GetContentAsync(context))
{
await stream.CopyToAsync(context.Response.OutputStream);
}
}
#region IHttpAsyncHandler
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
return new AsyncResult(cb, extraData, CopyAsync(context));
}
public void EndProcessRequest(IAsyncResult result)
{
// at this point, the task has compeleted
// we use Wait() only to re-throw any errors
((AsyncResult)result).Task.Wait();
}
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
throw new NotImplementedException();
}
#endregion
#region AsyncResult
class AsyncResult : IAsyncResult
{
object _state;
Task _task;
bool _completedSynchronously;
public AsyncResult(AsyncCallback callback, object state, Task task)
{
_state = state;
_task = task;
_completedSynchronously = _task.IsCompleted;
_task.ContinueWith(t => callback(this), TaskContinuationOptions.ExecuteSynchronously);
}
public Task Task
{
get { return _task; }
}
#region IAsyncResult
public object AsyncState
{
get { return _state; }
}
public System.Threading.WaitHandle AsyncWaitHandle
{
get { return ((IAsyncResult)_task).AsyncWaitHandle; }
}
public bool CompletedSynchronously
{
get { return _completedSynchronously; }
}
public bool IsCompleted
{
get { return _task.IsCompleted; }
}
#endregion
}
#endregion
}
关于c# - 从任务继续写入 ASP.NET 响应输出流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24510448/