Wir haben Windows-Dienst, der gut läuft, bis irgendwelche Ausnahmen im Prozess auftraten. Es enthält zwei Threads
(GenerateInvoice und GenerateReport). Diese Threads werden blockiert und führen zu einer DeadLock-ähnlichen Situation, vor allem wenn die CPU-Auslastung auf unserem DataBase-Server hoch ist.Windows-Dienst läuft, führt aber keinen Code aus
Wir haben einige Änderungen im Code vorgenommen, um solche Situationen zu behandeln, wie hinzugefügt unter Bedingung unter Code aber immer noch es funktioniert nicht. Unten ist die OnStart()
Methode der Dienstleistung:
protected override void OnStart(string[] args)
{
try
{
log.Debug("Starting Invoice Generation Service");
_thread = new Thread(new ThreadStart((new GenerateInvoice()).Process));
_thread.IsBackground = true;
_thread.Start();
_reportThread = new Thread(new ThreadStart((new GenerateReport()).Process));
_reportThread.IsBackground = true;
_reportThread.Start();
}
catch (Exception ex)
{
log.Error("Error in Invoice Generation Service:", ex);
}
}
Hier ist der Verarbeitungscode des ersten Thread: GenerateInvoice
public void Process()
{
while (isProcessActive)
{
try
{
DBBilling obj = new DBBilling();
DataTable dtInvoiceID = obj.readData(@"SELECT * FROM (SELECT ird.BillByType, ird.InvoiceID, ir.BeginDate, ir.EndDate, ir.SendToQB, ir.SendEmail,
i.ARAccountID, i.ARAccountHotelID, i.invoiceNumber,i.[STATUS],UPDATETIME,row_number() over (PARTITION BY ird.INVOICEID ORDER BY UPDATETIME DESC) AS row_number
FROM Invoices i JOIN InvoicesRunRequestDetails ird ON ird.InvoiceID=i.InvoiceID
JOIN InvoicesRunRequest ir ON ird.RequestID = ir.RequestID
Where i.[STATUS] = 'PENDING') AS rows
WHERE ROW_NUMBER=1 ORDER BY UPDATETIME");
processCounter = 0;
#region process
if (dtInvoiceID != null && dtInvoiceID.Rows.Count > 0)
{
//some code here..
}
#endregion
}
catch (Exception ex) //Mantis 1486 : WEBPMS1 Disk Space : 10 Aug 2016
{
log.ErrorFormat("Generate Invoice -> Process -> InnLink Billing Execute Query Exception. Error={0}", ex);
if(DBBilling.dbConnTimeoutErrorMessage.Any(ex.Message.Contains))
{
processCounter++;
if (processCounter >= 1) //Need to change to 25 after Problem Solve
{
isProcessActive = false;
log.ErrorFormat("Generate Invoice -> Process -> RunInvoice Service exiting loop"); //From here control is not going back
}
else
System.Threading.Thread.Sleep(5000); //Sleep for 5 Sec
}
}
}
}
Bearbeitung des zweiten Thread dh Gene Code:
public void Process()
{
AppSettingsReader ar = new AppSettingsReader();
string constr = (string)ar.GetValue("BillingDB", typeof(string));
SqlConnection con = new SqlConnection(constr);
while (isProcessActive)
{
try
{
DBBilling obj = new DBBilling();
DataTable dtReportRunID = obj.readData(@"SELECT ReportRunID,MonYear, BeginDate, EndDate FROM ReportRunRequest
Where [STATUS] = 'PENDING' ORDER BY ReportRunID");
processCounter = 0;
if (dtReportRunID != null && dtReportRunID.Rows.Count > 0)
{
//some code here..
}
}
catch (Exception ex) //Mantis 1486 : WEBPMS1 Disk Space : 10 Aug 2016
{
log.ErrorFormat("Generate Report -> Process -> InnLink Billing Execute Query Exception. Error={0}", ex);
if (DBBilling.dbConnTimeoutErrorMessage.Any(ex.Message.Contains))
{
processCounter++;
if (processCounter >= 1) //Need to change to 25 after Problem Solve
{
isProcessActive = false;
log.ErrorFormat("Generate Report -> Process -> RunInvoice Service Exiting loop"); //From here control is not going back
}
else
System.Threading.Thread.Sleep(5000); //Sleep for 5 Sec
}
}
}
}
was möglich Lösung, um solche Bedingungen zu vermeiden?
nur Hintergrund-Threads Mit problematisch ist. Ich bin überrascht, dass der Dienst lange genug läuft, um etwas Nützliches zu erledigen. Es sollte kurz nach dem Start herunterfahren, da keine Vordergrundfäden vorhanden sind. –
Warum verwenden Sie nicht einen 'Timer' außer der unbestimmten While-Schleife? Es ist keine gute Übung und kann Sie zu einigen Fehlern bringen. Und 'Thread.Sleep()' zu verwenden ist auch keine gute Übung. Sie sollten den Ruhezustand nur zum Debuggen verwenden. –
@Damien_The_Unbeliever, wo ist kein Problem, Hintergrund-Threads im Dienst zu verwenden. Der Service funktioniert so lange, bis Sie ihn stoppen. Es ist gut, in Windows-Hintergrundthreads zu verwenden. In diesem Fall können Sie Ihren Dienst problemlos beenden. –