简体   繁体   English

长期运行的WCF服务即将终止的原因是什么?

[英]Reasons for long-running WCF service dying?

I have a long-running WCF service, hosted in IIS, that handles printing without any user interaction. 我有一个长期运行在IIS中的WCF服务,该服务无需任何用户交互即可处理打印。 After about 2 hours of looping through 1000 print jobs, the WCF service just seems to die. 在循环执行1000个打印作业大约2个小时后,WCF服务似乎消失了。 The log file I track indicates that the last print job was sent to the printer, but it never returns success nor failure (again, according to the log file). 我跟踪的日志文件指示上次打印作业已发送到打印机,但是它永远不会返回成功或失败(同样,根据日志文件)。

From the log file, it would normally say: 从日志文件中,通常会说:

2015-12-17 19:00:23,673 [27] INFO Barn.WCF.SysPrsPrintServer - Sending Print Job... PrintDocumentId=168;PrintSectionId=742;CustomerId=112702;DeliveryAddressId=474984;DocumentName=/SystemProcesses/Reports/CertificateOfRegistry;PrinterLocation=HB-MFP1;PrinterPaperSource=Cassette 3 2015-12-17 19:00:23,673 [27]信息Barn.WCF.SysPrsPrintServer-正在发送打印作业... PrintDocumentId = 168; PrintSectionId = 742; CustomerId = 112702; DeliveryAddressId = 474984; DocumentName = / SystemProcesses / Reports / CertificateOfRegistry ; PrinterLocation = HB-MFP1; PrinterPaperSource =纸盒3

2015-12-17 19:00:32,626 [27] INFO Barn.WCF.SysPrsPrintServer - PdfPrintHandler.Print: Printer HB-MFP1 indicates the print job is complete. 2015-12-17 19:00:32,626 [27]信息Barn.WCF.SysPrsPrintServer-PdfPrintHandler.Print:打印机HB-MFP1指示打印作业已完成。

But the last log file entry is: 但是最后一个日志文件条目是:

2015-12-17 19:00:32,688 [27] INFO Barn.WCF.SysPrsPrintServer - Sending Print Job... PrintDocumentId=169;PrintSectionId=742;CustomerId=112702;DeliveryAddressId=474984;DocumentName=/SystemProcesses/Reports/CertificateOfRegistry;PrinterLocation=HB-MFP1;PrinterPaperSource=Cassette 3 2015-12-17 19:00:32,688 [27]信息Barn.WCF.SysPrsPrintServer-正在发送打印作业... PrintDocumentId = 169; PrintSectionId = 742; CustomerId = 112702; DeliveryAddressId = 474984; DocumentName = / SystemProcesses / Reports / CertificateOfRegistry ; PrinterLocation = HB-MFP1; PrinterPaperSource =纸盒3

Can you see how this might be possible that I get no message back at all? 您能看到没有任何回信的可能性吗? Is it possible the WCF service just died or IIS recycled the app pool or something like that? WCF服务是否可能刚刚终止或IIS回收了应用程序池或类似的东西? So without further ado, here is my class: 因此,事不宜迟,这是我的课程:

using System;
using System.Collections.Generic;
using System.Drawing.Printing;
using System.IO;
using System.Threading;
using log4net;
using Aspose.Pdf.Facades;

namespace Barn.API.Print.PrintHandlers
{
    public class PdfPrintHandler
    {
        private const int LargePdfByteCount = 3000000;
        private readonly ILog _log;
        private readonly ManualResetEvent _resetEvent = new ManualResetEvent(false);

        public PdfPrintHandler(ILog log)
        {
            _log = log;

            var license = new Aspose.Pdf.License();
            var pathLicense = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "bin\\Aspose.Pdf.lic";
            license.SetLicense(pathLicense);
        }

        /// <summary>
        /// Prints the specified stream.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <param name="printerSettings">The printer settings.</param>
        /// <param name="pageSettings">The page settings.</param>
        /// <param name="timeout">The timeout.</param>
        /// <param name="errors"></param>
        /// <returns>The status of the print job.</returns>
        public PrintJobStatusEnum Print(Stream stream, PrinterSettings printerSettings, PageSettings pageSettings, PrintDocumentModel printJob, int timeout, out List<string> errors)
        {

            errors = new List<string>();

            // Reset the wait handler to make sure the event is not signaled
            _resetEvent.Reset();

            // Set attributes for printing
            var viewer = new PdfViewer
            {
                AutoResize = true, 
                AutoRotate = true, 
                PrintPageDialog = false,
                PrintAsImage = false
            };

            // Add an event listener when print job sent to printer
            viewer.EndPrint += ViewerOnEndPrint;

            //Print document using printer and page settings
            try
            {
                _log.InfoFormat("Sending Print Job... PrintDocumentId={0};PrintSectionId={1};CustomerId={2};DeliveryAddressId={3};DocumentName={4};PrinterLocation={5};PrinterPaperSource={6}",
                    printJob.PrintDocumentId, 
                    printJob.PrintSectionId != null ? printJob.PrintSectionId.ToString() : "null", 
                    printJob.CustomerId != null ? printJob.CustomerId.ToString() : "null", 
                    printJob.DeliveryAddressId != null ? printJob.DeliveryAddressId.ToString() : "null", 
                    printJob.DocumentName != null ? printJob.DocumentName : "null", 
                    printJob.PrinterLocation != null ? printJob.PrinterLocation : "null",
                    pageSettings.PaperSource.SourceName != null ? pageSettings.PaperSource.SourceName : "null");

                // Print
                if (stream.Length <= LargePdfByteCount)
                {
                    // Bind the stream then print
                    viewer.BindPdf(stream);
                    viewer.PrintDocumentWithSettings(pageSettings, printerSettings);
                }
                else
                {
                    // Use a more efficient printing method with larger documents
                    viewer.PrintLargePdf(stream, pageSettings, printerSettings);
                }

                // Block until the event finishes or timeout reached
                _resetEvent.WaitOne(TimeSpan.FromMinutes(timeout));

                // Check the print status
                if (viewer.PrintStatus != null)
                {
                    // An exception was thrown
                    var ex = viewer.PrintStatus as Exception;
                    if (ex != null)
                    {
                        // Get exception message
                        _log.Error("PdfPrintHandler.Print: Print Error: " + ex.Message + ex.StackTrace, ex);
                        errors.Add(ex.Message);
                    }
                    return PrintJobStatusEnum.Error;
                }
                else
                {
                    // No errors were found. Printing job has completed successfully
                    _log.InfoFormat("PdfPrintHandler.Print: Printer {0} indicates the print job is complete.", printerSettings.PrinterName);
                    return PrintJobStatusEnum.Printed;
                }
            }
            catch (Exception e)
            {
                _log.Error("PdfPrintHandler.Print Exception: " + e.Message + e.StackTrace, e);
                errors.Add(e.Message);
            }
            finally
            {
                viewer.Close();
            }

            return PrintJobStatusEnum.Error;
        }

        private void ViewerOnEndPrint(object sender, PrintEventArgs printEventArgs)
        {
            // Signal the event is finished
            _resetEvent.Set();
        }
    }
}

WCF Service Interface: WCF服务接口:

using System.ServiceModel;

namespace Barn.WCF
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "ISysPrsPrintServer" in both code and config file together.
    [ServiceContract]
    public interface ISysPrsPrintServer
    {
        [OperationContract]
        string DoWork(string data);
    }
}

Here it is in the Windows event log: 它在Windows事件日志中:

A worker process with process id of '3236' serving application pool 'testws.mydomain.ca' was shutdown due to inactivity. 由于不活动,关闭了为应用程序池“ testws.mydomain.ca”提供服务的进程ID为'3236'的辅助进程。 Application Pool timeout configuration was set to 20 minutes. 应用程序池超时配置设置为20分钟。 A new worker process will be started when needed. 需要时将启动一个新的工作进程。

So IIS seems to have thought that there was 20 minutes of inactivity because the WCF service is called asynchronously. 因此IIS似乎认为20分钟处于不活动状态,因为WCF服务是异步调用的。 The process is working away, but IIS decided to recycle the application pool in the middle of the process running. 该进程正在运行,但是IIS决定在进程运行的中间阶段回收应用程序池。

I changed the settings in IIS on the application pool according to this: https://serverfault.com/questions/333907/what-should-i-do-to-make-sure-that-iis-does-not-recycle-my-application 我根据此更改了应用程序池上IIS中的设置: https : //serverfault.com/questions/333907/what-should-i-do-to-make-sure-that-iis-does-not-recycle-我的应用程序

I would suggest checking the operation contracts of your print methods. 我建议检查您的打印方法的操作合同。 I have seen WCF services fail out when the isOneWay attribute is not set or is set to false on a void method. 我已经看到,当未设置isOneWay属性或在void方法上将其设置为false时,WCF服务会失败。 try something like this 尝试这样的事情

    [OperationContract(IsOneWay=true)]
    public void PrintDocumentWithSettings(PageSettings settings, PrinterSettings settings);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM