任务停止在不同的环境中工作

时间:2016-10-05 13:28:55

标签: c# asp.net task

我很难用这个。

所以在我的asp.net应用程序中有这样一种方法:

public CopyResponse thirdStage(CopyRequest request)
{
    CopyCCResponse response = new CopyCCResponse();

    Task.Run(() =>
    {
        performCopying(request);
    });

    return response;
}

private void performCopying(CopyCCRequest request)
{
    using (Repository = new myDbContext())
    {
        // do some initial action
        try
        {
        // in general it looks like below
            foreach(var children in father)
            {
                var newChildren = chldren.Copy();
                Repository.Childrens.Add(newChildren);

                foreach (var grandchldren in children.grandchildrens)
                {
                    var newGrandchildren = grandchldren.Copy();
                    newGrandchildren.Parent = newChildren;

                    Repository.Grandchildrens.Add(newGrandchildren);
                }

                Repository.SaveChanges();
            }
        }
        catch (Exception ex)
        {
            // log that action failed

            throw ex;
        }
    }
}

此方法和所有其他方法(有一些类似的方法)在本地计算机上的设计工作没有任何问题。

不幸的是,在另一个环境中,这些方法失败了:

  • 复制较小的数据部分可以正常工作。但是当有超过3000个对象要操作时,方法会失败。
  • 主要应用程序仍然正确响应。
  • 大部分操作都很顺利(大多数数据都被复制并保存在数据库中)
  • 应用程序不会进入catch块。未执行复制失败的说明。错误处理程序没有捕获异常(BTW,我知道默认情况下应用程序无法捕获独立任务的异常,我编写了我的处理程序,因此它会设法这样做)。
  • 复制停止后,IIS工作进程似乎占用超过300MB和0%的处理器能力。服务器上超过一半的RAM仍然是免费的。
  • 我查看了Windows事件日志,但没有找到任何内容。

您对我如何处理此问题有任何建议吗?

1 个答案:

答案 0 :(得分:1)

您无法从IIS内部执行可靠的“即发即弃”任务,如果未提供该站点,则应用程序池将在一段时间后关闭其AppDomain

使用的两个选项是:

HostingEnvironment.QueueBackgroundWorkItem告诉IIS您正在做背景工作。这将使服务器知道工作,并且在它终止进程之前,它将延迟关闭(最多默认最多90秒)。

public CopyResponse thirdStage(CopyRequest request)
{
    CopyCCResponse response = new CopyCCResponse();

    HostingEnvironment.QueueBackgroundWorkItem(() =>
    {
        performCopying(request);
    });

    return response;
}

另一个选择是使用专为在Hangfire.io等IIS中进行后台工作而设计的第三方库,这将在IIS内部运行一项服务,并尝试将实例保持活动直到工作已经完成了。您还可以将Hangfire配置为单独运行,因此您无需依赖IIS实例的生命周期。

public CopyResponse thirdStage(CopyRequest request)
{
    CopyCCResponse response = new CopyCCResponse();

    BackgroundJob.Enqueue(() =>
    {
        performCopying(request);
    });

    return response;
}

注意,使用具有单独进程的hangfire可能需要对performCopying(CopyCCRequest request)进行一些重新设计以支持从单独的进程运行,从IIS实例内部使用它不需要任何更改。