【发布时间】:2019-01-21 16:49:06
【问题描述】:
我对这个问题很恼火。
这一切都是因为我们记录的太多,这意味着人们会将请求/响应 dto 的文本内容(主要是 xml)写入日志文件,从而使文件无法随便阅读。
我的想法是将他们插入到日志文件中的内容,然后将其流式传输到网络文件管理器(另一个问题,但易于管理)。最终,日志语句将包含流式传输文件的路径,如果您想打开它,请使用它。
这是第 1 版:
private static void WriteFileAsync(string path, string text)
{
Task.Factory
.StartNew(() => File.WriteAllText(path, text))
.ContinueWith(tsk =>
{
Log.Error(tsk.Exception, "FileExtensions.PersistPayload");
}, TaskContinuationOptions.OnlyOnFaulted);
}
版本 1 最初运行良好,我的测试表明它至少是在另一个线程上完成的,但仅此而已。我无法验证这是否有助于或妨碍 Web 应用程序的性能和日志记录 sub-subsystem,但至少大量文本已从日志语句中删除并替换为文件路径。
第 2 版:尝试使用内置的 File 对象并异步写入,但事实并非如此,或者它被缓冲了。
private static async void WriteFileAsync(string path, string text)
{
using (var writer = File.CreateText(path))
{
await writer.WriteAsync(text);
}
}
第 3 版:当我使用流来帮助创建文件时。编写此方法的关键是 @StephenCleary 在他的一篇帖子或关于 SO 的答案中的内容,除非您使用 FileStream 构造函数,该构造函数采用下面概述的参数“useAsync”,否则流不是异步的。
private static async Task WriteFileAsync(string path, string text)
{
byte[] encodedText = Encoding.Unicode.GetBytes(text);
using (var stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
{
await stream.WriteAsync(encodedText, 0, encodedText.Length);
}
}
到目前为止,我对设置很满意,并且在许多 ASP.NET MVC 5 应用程序中都有它。但是,其中一些 Web 项目 349c5851-65df-11da-9384-00065b846f21 有 WCF 端点挂在它们上面,而另一些有 ASMX 端点。如果您调用 asmx 文件方法,则会引发此异常:
System.InvalidOperationException: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing.
所以我的问题是:“有没有办法异步编写文件并让它在 Web API 控制器、WCF 端点和 WebService 端点中工作而不会死?”
更新
好吧,我认为没有一点代码就不可能让 asmx 处理程序完成它。我使用了来自 Wintelects Jeff Prosise 的代码,它实际上将默认的 asmx 处理程序换成了支持异步的 STA 处理程序,但这似乎有点过头了。我只是不打算支持 asmx 文件并继续前进。
谢谢你, 斯蒂芬
【问题讨论】:
-
方法不是问题,变体 3 应该可以正常工作。如果您使用网络表单,则需要将页面标记为异步,如错误所示并注册您的异步方法。 Docs
-
@JSteward 我们没有使用网络表单,这些只是服务和/或控制器。
-
你能贴出从 asmx 文件中调用你的日志记录方法的代码吗?
-
@JSteward 我看不出这有什么关系,而且它在服务中隐藏了好几层。假设在 *.svc 文件中使用了相同的代码并且它可以正常工作。
-
我认为这是相关的,因为只有在调用
WebMethod时才会出现错误。如果您的日志记录方法在其他任何地方都可以正常工作,那么您的问题可能是由于在较旧的 Asp.net 框架中处理异步操作所致。至于buried,也许你可以创建一个重现相同错误的MCVE。
标签: c# asp.net async-await