在我的MVC控制器中,我有一个动作将填充我稍后将使用的流:
[HttpPost]
public async Task<HttpResponseMessage> BuildFileContent(FileParameters fileParams)
{
byte[] output;
if (fileParams != null)
{
using (var stream = new MemoryStream())
{
await Task.Run(() => PopulateFile(fileParams, stream)); // Here i populate the stream
stream.Flush();
output = stream.ToArray();
}
var guid = Guid.NewGuid().ToString();
FileContents.Add(guid, output); // just save the content for later use
return this.Request.CreateResponse(HttpStatusCode.OK, new { Value = guid });
}
return this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Invalid parameters");
}
我遇到了这个问题,因为ReSharper在access on disposed closure
行发出警告:PopulateFile(fileParams, stream)
并指出stream
。
我已经搜索了它的含义,它似乎警告我可以使用已经处理过的流。
我想等待流的填充,因为任务可能需要很长时间。
有没有办法让我可以在没有ReSharper发出此警告的情况下等待流的填充?
此外,我在stream
子句中调用using
,直到我调用flush或者using子句的最后一行被执行时才应该处理流?那么为什么ReSharper会警告访问一条被处理的流?
答案 0 :(得分:5)
Resharper警告你,因为你正在lambda表达式中使用流,该表达式基本上可以在using
范围内运行,而不仅仅在ObjectDisposedException
范围内运行。
如果这是您的代码,您可以在任务结束之前处理该流,并且您手上会有Task task = null;
using (var stream = new MemoryStream())
{
task = Task.Run(() => PopulateFile(fileParams, stream)); // Here i populate the stream
stream.Flush();
output = stream.ToArray();
}
await task;
:
await
在您的情况下,您 using
该操作并仅在该操作完成后处理该流。所以基本上你是清楚的,但Resharper显然不知道。
要完全清除警告,您可以将await Task.Run(() =>
{
using (var stream = new MemoryStream())
{
PopulateFile(fileParams, stream);
stream.Flush();
output = stream.ToArray();
}
});
范围放在任务中:
{{1}}
我建议你这样做。
答案 1 :(得分:1)
@ I3arnon的答案是完全正确的,但我想解决一个重点。
我想等待流的填充,因为任务可能需要很长时间。
这是一个崇高的目标,但受益于await
完全取决于PopulateFile
的实施,这可能不是一种异步方法,从它的调用方式来判断。无论何时你做await Task.Run(() => DoSomethingSynchronously())
之类的事情,你在释放线程方面都没有任何收获。
我建议仔细查看PopulateFile,确定缓慢来自哪里,看看是否可以利用任何真正的异步API来处理Web access,file I/O等等。如果你可以将PopulateFile重写为异步方法(即使用类似async Task PopulateFileAsync(...)
的签名),利用这些API,您可以在等待长时间运行的操作时真正释放线程,并且可以直接等待它,而无需Task.Run
:
using (var stream = new MemoryStream())
{
await PopulateFileAsync(fileParams, stream)); // Here i populate the stream
stream.Flush();
output = stream.ToArray();
}
作为奖励,上述代码不应引起R#的投诉。