IIS托管模块:AddOnBeginRequestAsync无需有效IAsyncResult的实现问题
问题:IIS异步模块中IAsyncResult返回值引发的错误
要实现IIS托管模块的异步处理,将搜索日志保存到本地文件。使用AddOnBeginRequestAsync时,要求BeginRequest方法返回IAsyncResult类型,EndRequest方法需接收该参数。过程中遇到两个错误:
- 返回
null时触发System.NullReferenceException - 自定义
NullAsyncResult实现IAsyncResult接口后,调用时出现CS1955错误:不可调用的成员“NullAsyncResult”不能用作方法
相关代码
原BeginRequest方法代码
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; }
自定义NullAsyncResult类代码
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; } } }
修改后的BeginRequest方法代码
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(); }
错误原因及修复方案
1. CS1955错误修复
NullAsyncResult是自定义类,不是方法,不能直接用NullAsyncResult()调用,需要实例化对象,将返回语句改为:
return new NullAsyncResult();
2. NullReferenceException错误修复
ASP.NET不允许BeginRequest返回null,必须返回一个有效的IAsyncResult实例,所以必须使用自定义的NullAsyncResult或者.NET内置的实现(如TaskAsyncResult)。
3. 其他代码问题修复
- 变量作用域问题:原代码中
searchData在using块内定义,外部无法访问,会导致编译错误,需将变量声明移到using块外:string searchData; using (var reader = new StreamReader(HttpContext.Current.Request.InputStream)) { searchData = HttpUtility.UrlDecode(reader.ReadToEnd()); } - 异步流程规范:即使操作是同步完成的,也需要调用传入的
AsyncCallback委托,通知ASP.NET异步操作已完成:var asyncResult = new NullAsyncResult(); cb?.Invoke(asyncResult); return asyncResult; - 真正实现异步:如果要避免阻塞请求线程,推荐使用异步文件写入方法
File.AppendAllTextAsync,结合Task来实现真正的异步处理:// 在BeginRequest中启动异步任务 var task = File.AppendAllTextAsync(Path.Combine(workDir, "search_log.txt"), searchData); // 将Task包装为IAsyncResult返回 return task.AsAsyncResult(); // 在EndRequest中等待任务完成 private void EndRequest(IAsyncResult ar) { var task = ((Task)ar); task.Wait(); }
内容的提问来源于stack exchange,提问作者ValB
相关产品推荐
相关产品推荐

