如何从ASMX端点异步创建/写入文件?

时间:2018-02-22 21:20:26

标签: c# asp.net async-await

我对这个问题感到烦恼。

这一切都开始是因为我们记录太多了,这意味着人们会将请求/响应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 Controller,WCF端点和WebService端点中工作而不会死?”

更新

好吧,我认为没有一点代码就可以让asmx处理程序去做。我使用过Wintelects Jeff Prosise的代码,它实际上交换了支持异步的STA处理程序的默认asmx处理程序,但这似乎有点过分了......我只是不支持asmx文件并继续前进。 / p>

谢谢你, 斯蒂芬

1 个答案:

答案 0 :(得分:0)

我最终实现了来自Wintelects Jeff Prosise的MSDN文章(Wicked Code)中的代码,其中当前的asmx HTTP Handler被删除并替换为挂钩到ASPX页面生命周期的文章,该生命周期可以异步工作。从长远来看,我正在远离旧的asmx技术。