【问题标题】:Task Persistence C#任务持久性 C#
【发布时间】:2012-05-27 13:11:37
【问题描述】:

我很难让我的任务保持持久性并通过 WCF 服务无限期地运行。我可能以错误的方式这样做,并愿意接受建议。

我有一个任务开始处理任何进入 BlockingCollection 的请求。据我了解,GetConsumingEnumerable() 方法应该允许我在数据到达时持续提取数据。它本身没有问题。我能够处理数十个请求,而没有一个错误或缺陷,使用 Windows 表单填写请求并提交它们。一旦我对这个过程充满信心,我就会通过 asmx Web 服务将它连接到我的站点,并使用 jQuery ajax 调用来提交请求。

站点根据提交的 url 提交请求,Web 服务从 url 下载 html 内容并在内容中查找其他 url。然后它继续为它找到的每个 url 创建一个请求,并将其提交给 BlockingCollection。在 WCF 服务中,如果应用程序处于联机状态(即任务已启动),它会使用 GetConsumingEnumerable 通过 Parallel.ForEach 拉取请求并处理请求。

这适用于前几次提交,但随后任务意外停止。当然,这比我在测试中模拟的请求多 10 倍——但我预计它只会节流。我相信问题出在我启动任务的方法中:

 public void Start()
        {
            Online = true;

            Task.Factory.StartNew(() =>
            {
                tokenSource = new CancellationTokenSource();
                CancellationToken token = tokenSource.Token;
                ParallelOptions options = new ParallelOptions();
                options.MaxDegreeOfParallelism = 20;
                options.CancellationToken = token;

                try
                {
                    Parallel.ForEach(FixedWidthQueue.GetConsumingEnumerable(token), options, (request) =>
                    {
                        Process(request);
                        options.CancellationToken.ThrowIfCancellationRequested();

                    });
                }
                catch (OperationCanceledException e)
                {
                    Console.WriteLine(e.Message);
                    return;
                }

            }, TaskCreationOptions.LongRunning);

        }

我曾考虑将其移至 WF4 服务中,然后将其连接到工作流中并使用工作流持久性,但除非必要,否则我不愿意学习 WF4。如果需要更多信息,请告诉我。

【问题讨论】:

标签: wcf task-parallel-library persistent taskfactory blockingcollection


【解决方案1】:

您显示的代码本身就是正确的。

但是有一些事情可能会出错:

  • 如果发生异常,您的任务将停止(当然)。尝试添加 try-catch 并记录异常。
  • 如果您在托管环境(ASP.NET、WCF、SQL Server)中启动工作线程,宿主可以任意决定(没有理由)关闭任何工作进程。例如,如果您的 ASP.NET 站点在一段时间内处于非活动状态,则应用程序将关闭。我刚才提到的主机不是为了运行自定义线程而设计的。使用专用应用程序 (.exe) 甚至 Windows 服务,您可能会获得更大的成功。

【讨论】:

  • 我之前抛出了一个问题来重新启动系统——这似乎不起作用,所以我删除了它。根据您的说法,ASP.NET 很可能是罪魁祸首。我确实设置了工作人员不会超时,并且我将 WCF 移动到与 Web 服务(asmx)不同的 AppPool 中,希望它可以防止任何冲突。我想我有很多学习要做。我尝试通过 net.tcp 托管服务,但无法让端点公开。它在 visual stuidos 中运行良好 - 但作为 Windows 服务安装时会出错,指示连接被拒绝。
  • 当你在一个宿主进程中启动线程时,宿主会主动对抗你。听起来您正在构建一个网络爬虫。我会将爬虫放在一个长期运行的 Windows 服务中,并让该服务与正常的 WCF 服务或向 Windows 服务发送命令的 asp.net 网站通信。这样你就避免了所有问题。
  • 我最终将 WCF 服务主机移动到 Window 服务中,认为这可能会解决问题 - 但症状相同。我可以毫无问题地添加到集合中,但如果它在我向集合提交其他数据时枚举任务中的阻塞集合 - 它会导致服务崩溃。在视觉工作室中,这不会发生。当我使用 Windows 窗体作为客户端并在进程运行时提交请求时,它也不会发生。它仅在我开​​始通过 asmx 提交请求(添加到集合)时才开始发生。
  • 如果有人可以提出一种更好的方法来使用 TPL 持久处理数据集合 - 那太好了!我一直碰壁,这个过程让我在这个项目上耽误了 2 周时间。
  • “崩溃”究竟是什么意思?您可以捕获并发布异常吗?您看到哪些车祸症状?
【解决方案2】:

原来这个问题的原因是 WCF 绑定配置。该任务突然停止,因为 WCF 由于打开超时而终止了连接。打开超时设置是请求在超时之前等待服务打开连接的时间。在某些情况下,它达到了 10 个最大连接的限制,并导致传入连接被备份以等待连接。我确保在事务完成后关闭了与主机的所有连接 - 所以我放弃了增加最大连接数和打开超时期限。在此之后 - 它运行完美。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-15
    • 1970-01-01
    • 2015-03-23
    相关资源
    最近更新 更多