g3r*_*rv4 10 .net iis task-parallel-library
我正在构建一个Logging库,用于存储Azure表上的所有内容.写入该表显然需要花费大量时间(从不超过1秒,但仍然太多使用户等待),因此Log方法返回一个LogResult实例,这里是类
public class LogResult
{
public string Id { get; set; }
public Task LoggingTask { get; set; }
public LogResult(string id, Task task)
{
Id = id;
LoggingTask = task;
}
}
Run Code Online (Sandbox Code Playgroud)
以下是Log方法的完成方式
return new LogResult(id, Task.Factory.StartNew(() =>
DoLogInAzure(account, id, exception, request))
);
Run Code Online (Sandbox Code Playgroud)
为调用者提供等待它完成的选项(例如,如果它是一个控制台应用程序).我面临的问题是IIS 在返回用户响应之前不应该等待它......如果我不等待它,IIS并不总是执行任务.这个想法是向用户显示一条消息"......如果您联系我们,请务必提及您的问题编号XXX",并且不要让他等到日志条目写完.
有没有办法强制IIS等待任务完成,即使它返回响应?我想我可能需要编写一个异步获取请求的Windows服务,但是添加日志条目看起来很多工作......特别是如果我可以强制IIS等待它.
谢谢你的任何想法!
g3r*_*rv4 10
感谢Damian Schenkelman和Phil Haack的博客文章,我找出了问题和解决方案.问题是IIS在需要处理新请求时重用这些线程.由于它不知道我的任务正在做一些工作,它重用了那个线程(这是有道理的).然后,我只需要通知IIS我正在使用该线程并且它不能被重用(因此,它必须重用另一个线程,创建一个新线程,或让它等待).我最终使用自己的TaskFactory处理任务创建,并自动在IIS中注册通知程序.为了完整,帮助其他一些与我有同样问题的人,并阅读其他建议,这就是我所做的
public class IISNotifier : IRegisteredObject
{
public void Stop(bool immediate)
{
// do nothing, I only run tasks if I know that they won't
// take more than a few seconds.
}
public void Started()
{
HostingEnvironment.RegisterObject(this);
}
public void Finished()
{
HostingEnvironment.UnregisterObject(this);
}
}
Run Code Online (Sandbox Code Playgroud)
然后
public class IISTaskFactory
{
public static Task StartNew(Action act)
{
IISNotifier notif = new IISNotifier();
notif.Started();
return Task.Factory.StartNew(() => {
act.Invoke();
notif.Finished();
});
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当我想开始执行日志任务时
return new LogResult(id, IISTaskFactory.StartNew(() =>
DoLogInAzure(account, id, exception, request))
);
Run Code Online (Sandbox Code Playgroud)
您可以在https://github.com/gmc-dev/IISTask上查看(并下载代码)
| 归档时间: |
|
| 查看次数: |
4503 次 |
| 最近记录: |