尝试将搜索日志保存到本地文件中。我需要异步处理程序,但AddOnBeginRequestAsync需要从BeginRequest,EndRequest返回IAsyncResult。如何在没有它的情况下完成此操作?返回null -不起作用。
这是IIS管理的模块。
public void Dispose()
{
}
public bool IsReusable
{ get { return false; } }
public void Init(HttpApplication app)
{
app.AddOnBeginRequestAsync(BeginRequest, EndRequest);
}
private IAsyncResult BeginRequest(object sender, EventArgs e, AsyncCallback cb, object extraData)
{
string reqPath = HttpContext.Current.Request.Url.PathAndQuery;
bool correctString = reqPath.Contains("/?search=");
if (HttpContext.Current.Request.HttpMethod == "POST" && correctString)
{
using (var reader = new StreamReader(HttpContext.Current.Request.InputStream))
{
string searchData = HttpUtility.UrlDecode(reader.ReadToEnd());
}
File.AppendAllText(workDir + "search_log.txt", searchData);
}
}
private void EndRequest(IAsyncResult ar)
{
return;
}
当返回null添加到BeginRequest时,则发生错误“System.NullReferenceException”。
还尝试:
public class NullAsyncResult : IAsyncResult
{
public object AsyncState
{
get { return null; }
}
public System.Threading.WaitHandle AsyncWaitHandle
{
get { return null; }
}
public bool CompletedSynchronously
{
get { return true; }
}
public bool IsCompleted
{
get { return true; }
}
}
然后:
private IAsyncResult BeginRequest(object sender, EventArgs e, AsyncCallback cb, object extraData)
{
string reqPath = HttpContext.Current.Request.Url.PathAndQuery;
bool correctString = reqPath.Contains("/?search=");
if (HttpContext.Current.Request.HttpMethod == "POST" && correctString)
{
using (var reader = new StreamReader(HttpContext.Current.Request.InputStream))
{
string searchData = HttpUtility.UrlDecode(reader.ReadToEnd());
}
File.AppendAllText(workDir + "search_log.txt", searchData);
}
return NullAsyncResult();
}
出现错误:
CS1955 Non-callable member 'NullAsyncResult' cannot be used as a method.
1条答案
按热度按时间ruoxqz4g1#
使用
AddOnBeginRequestAsync
的目的是当你做一些异步的事情时,现在,你没有,你可以在Application_BeginRequest
中做同样的事情。然而,我认为你可以通过改变你的代码来异步写入文件。这将加快你的应用程序的速度,因为它允许你的应用程序在数据被写入文件的同时开始处理请求。这个异步代码可以通过使用
EventHandlerTaskAsyncHelper
来简化,这在this answer中有简要的描述。而且,当你反复使用
File.AppendAllText()
时,它的开销会很大。它必须打开文件,写入数据,关闭文件,所以你可以做的另一个改进是为文件使用一个静态变量,并在应用程序的生命周期内保持打开状态。这样你就不会经常打开和关闭文件了。您需要使用TextWriter.Synchronized
Package 文件流,以允许多个线程写入文件。但是,这仅适用于应用池只有一个工作进程的情况。另外,如果你将
InputStream
封装在StreamWriter
中并处理它(using
将执行此操作),那么它也会处理InputStream
,ASP.NET将无法再使用它。因此,你需要以不同的方式读取InputStream
,并将Position
返回到0
,以便ASP.NET可以重新读取流。您也不需要使用
HttpUtility.UrlDecode()
,因为您正在阅读请求的主体,而不是URL。为了简化代码,您可以只使用
Request.InputStream
而不是HttpContext.Current.Request.InputStream
,因为HttpApplication
类确实公开了Request
属性。我认为你甚至不需要一个模块来完成这个任务,因为你是在应用程序级别使用
AddOnBeginRequestAsync
的,你可以在你的Global.asax.cs
文件中完成这一切。我以前做过一些这样的事情,所以我可以分享我的代码。根据您的用例调整它,它看起来像这样:
我们在
Application_Start
中初始化logFile
,因为它在应用程序的生命周期中只运行一次,而Init
在每次示例化新的HttpApplication
类时都会运行,这在应用程序的生命周期中可能会发生很多次。我们希望它只运行一次。你也可以在声明中初始化logFile
,如果你能让workDir
成为一个静态值:你会注意到,如果你不需要记录任何东西,它会返回
Task.CompletedTask
,这就是你在必须返回Task
的方法中所做的,但是你没有做任何异步的事情。我还向
if
添加了一个条件,因此它只在实际存在数据时读取数据(Request.InputStream.Length > 0
)。