防止IIS在任务结束前终止它

时间:2012-09-30 22:05:54

标签: .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;
    }
}

以下是Log方法的完成方式

return new LogResult(id, Task.Factory.StartNew(() => 
    DoLogInAzure(account, id, exception, request))
);

为调用者提供等待它完成的选项(例如,如果它是控制台应用程序)。我面临的问题是IIS 不应该等待它,然后再向用户返回响应...如果我不等待它,IIS就不会总是< / em>执行任务。我们的想法是向用户显示一条消息“......如果您联系我们,请务必提及您的问题编号XXX”,并且不要让他等到日志条目写完。

有没有办法强制IIS等到任务完成,即使它返回响应?我想我可能需要编写一个异步获取请求的Windows服务代码,但是添加日志条目看起来很多工作......特别是如果我可以强制IIS等待它。

感谢您的任何想法!

4 个答案:

答案 0 :(得分:11)

来自Phil Hack的

This post讨论了如何在ASP.NET应用程序中运行后台任务。

答案 1 :(得分:9)

感谢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);
    }
}

然后

public class IISTaskFactory
{
    public static Task StartNew(Action act)
    {
        IISNotifier notif = new IISNotifier();
        notif.Started();
        return Task.Factory.StartNew(() => {
            act.Invoke();
            notif.Finished();
        });
    }
}

现在,当我想开始一个日志任务时,我就是

return new LogResult(id, IISTaskFactory.StartNew(() => 
    DoLogInAzure(account, id, exception, request))
);

您可以在https://github.com/gmc-dev/IISTask

查看(并下载代码)

答案 2 :(得分:0)

信息不够,但我怀疑它可能与GC相关,如果等待任务时它可以正常工作。为了您的目的,更好的方法是使用ETW(EventProvider)并为每个请求设置ActivityId。只需配置ETW会​​话即可将所有消息重定向到文件。您可以向最终用户显示ActivityId(Guid)。

答案 3 :(得分:0)

很抱歉没有将此添加为评论,我没有足够的代表。

https://msdn.microsoft.com/en-us/library/system.web.hosting.iregisteredobject(v=vs.110).aspx

  

应用程序只能有一个已注册类型的实例。

这似乎表明Gervasio Marchand接受的答案有点不正确,因为每次调用他的静态助手方法都会创建一个新的IISNotifier,它是一个IRegisteredObject。