ASP.NET C # fil exception avorté?
-
11-10-2019 - |
Question
Je suis en train de construire un petit travailleur de courrier électronique qui envoie mes e-mails. Le travailleur de courrier électronique fonctionne dans son propre fil. Le global.asax commence le fil et il court pour un tour avant de lancer cette exception. J'ai essayé de savoir où il jette, mais il semble être différent à chaque fois. Les enregistrements sont imprimés dans le fichier texte afin que les travaux, peut-être les fonctions Dispose?
Ceci est l'exception levée:
Démarrage d'un nouveau cycle dans l'e-mail travailleur en boucle
Aller dormir dans la travailleur email boucle
Une première chance exception de type 'System.Threading.ThreadAbortException' est produite dans mscorlib.dll
Une exception de type 'System.Threading.ThreadAbortException' est produite dans mscorlib.dll mais n'a pas été manipulés dans le code utilisateur
Ceci est le code pour le EmailWorker
public static class EmailWorker
{
public static void Work()
{
TimeSpan sleepTime = new TimeSpan(0, 1, 0);
for (; ; )
{
Debug.WriteLine("Starting a new round in the email worker for-loop");
try
{
// Get the records
CS_Code.UtopiaDataContext db = new CS_Code.UtopiaDataContext();
List<CS_Code.Global_Email> emailsToSend = (from xx in db.Global_Emails select xx).ToList();
// Write the records to a file (for now)
TextWriter writer = new StreamWriter(@"test.txt", true); // For debugging
foreach (var email in emailsToSend)
writer.WriteLine("To: " + email.Email_Address + ", Subject: " + email.Subject + ", uid:" + email.UserName.ToString());
writer.Close();
writer.Dispose();
// Delete the used records from the database
foreach (var email in emailsToSend)
db.Global_Emails.DeleteOnSubmit(email);
db.SubmitChanges();
db.Dispose();
Debug.WriteLine("Going to sleep in the email worker for-loop");
Thread.Sleep(sleepTime); // Sleep for 1 minute.
Debug.WriteLine("Just woke up in the email worker for-loop");
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
break;
}
}
}
}
Ceci est le fichier global.asax qui commence tout:
private static Thread EmailWorkerThread { get; set; }
void Application_Start(object sender, EventArgs e)
{
// Email worker thread
if ((EmailWorkerThread == null) || (!EmailWorkerThread.IsAlive))
{
ThreadStart ts = new ThreadStart(EmailWorker.Work);
EmailWorkerThread = new Thread(ts);
EmailWorkerThread.Start();
}
}
void Application_End(object sender, EventArgs e)
{
// Email worker thread
if ((EmailWorkerThread != null) || (EmailWorkerThread.IsAlive))
EmailWorkerThread.Abort();
EmailWorkerThread = null;
}
La solution
Le fil que vous créez est avortent par asp.net. Créer de longs fils sont en cours d'exécution un grand non-non en asp.net.
nous avons une solution de travail, que nous ne sommes pas fiers de ... Créer une minuterie qui processus emails en attente.
static Timer processTimer; // declare static at service level
// At the static constructor:
processTimer = new Timer(new TimerCallback(TimerTick), 60000, 10000, defaultInterval); //wait a minute before begin (dueTime = 60000)
Pour être carefull supplémentaire, au cas Timer_Tick, poignée à la plupart des e-mails de N, de sorte que les extrémités de timer tick, et une nouvelle monte ...
travaille sur notre environnement de production ...
Autres conseils
Vous devez déplacer le EmailWorker sur ASP.NET et en service Windows. Vous pouvez communiquer entre votre page Web et le service via WCF. ASP.NET n'est pas pour les tâches à long en cours d'exécution.
Le ThreadAbortException
se produit lorsque votre application se ferme vers le bas et que vous appelez EmailWorkerThread.Abort()
. Ce comportement est normal et il se produit dans des endroits aléatoires car le code peut être dans les différents « points » lorsque les appels Application_End
Abort()
sur le fil.
par MSDN , le ThreadAbortException
est un exception spéciale qui est toujours relancée même après avoir été manipulé par votre code. Il est destiné à vous faire savoir que le fil est en cours d'arrêt pour vous donner l'occasion de nettoyer.
application Vous est en cours d'arrêt probablement vers le bas parce que IIS est en cours d'arrêt du processus de travail après un certain laps de temps d'inactivité, ou une autre limitation imposée. Encore une fois, cela est à prévoir, les applications ASP.NET ont tendance à avoir « durée de vie limitée », en cours d'exécution tant des fils comme celui-ci ne sont pas vraiment une bonne idée.
Je ne sais pas quelle était votre question exacte, mais je l'espère, je répondu.
Le fil de l'enfant ne peut vivre aussi longtemps que le fil parent est vivant. Même si vous avez un fil défini dans ce qui semble être le niveau de l'application, je ne peux pas imaginer ce fil survive à l'extérieur du fil HttpRequest. Pour moi, cela signifie que le moment votre demande de fil se termine, votre enfant EmailWorkerThread se termine. Etant donné que le fil est en train de dormir, les tentatives de nouvelle ligne pour exécuter, mais il ne peut pas parce que le fil HttpRequest a déjà couru son cours.
ThreadAbortException
comme son nom l'indique, est jeté lorsqu'un thread fonctionne et est abandonnée. Cela se produit à cet endroit:
EmailWorkerThread.Abort();
Il ne peut pas être pris et il se produit lorsque vous application se termine.
serait une meilleure mise en œuvre pour remplacer la boucle infinie avec résiliable boucle .