Voici un exemple de programme (vous aurez besoin de la bibliothèque Enterprise pour l'exécuter). J'exécute 100 tâches dans une boucle, elles enregistrent un message dans le journal des événements. Je stocke la tâche générée dans le tableau des tâches et je la surveille simplement dans une boucle while.Obtention de l'objet EnterpriseLibrary Erreur LogWriter dans la boucle Tâches
Le problème est sur 100, les tâches aléatoires échouent et donnent l'erreur ci-dessous. D'après ce que je comprends, les tâches ont leur propre état, donc elles ne doivent pas interférer les unes avec les autres et la méthode Logger est statique, donc je ne sais pas où mon objet est jeté.
Pourquoi l'objet Logger est-il éliminé s'il est statique?
si je mets LOCK (objet) autour de mon code de l'enregistreur dans Task.Run() que cela fonctionne très bien. Est-ce une bonne idée ?
Erreur
à Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter.get_SyncLock() à Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter.ExecuteReadOperation (Action readOperation) chez Microsoft .Practices.EnterpriseLibrary.Logging.LogWriter.Write (journal LogEntry) à Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write (journal LogEntry) à WW.Test.TasksLoggingTest.b__1() dans c: \ tfs \ Report \ WWTest \ TasksLoggingTest.cs: ligne 7 9 à System.Threading.Tasks.Task`1.InnerInvoke() à System.Threading.Tasks.Task.Execute()
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Web.Hosting;
namespace Test
{
public class TasksLoggingTest
{
bool flag = true;
Thread T;
public static volatile bool IsWorkStarted = false;
public void Start()
{
while(flag)
{
try
{
if (IsWorkStarted == false)
{
IsWorkStarted = true;
T = new Thread(DoWork);
T.IsBackground = true;
T.Start();
}
}
catch(Exception e)
{
Console.WriteLine("Error starting thread");
}
finally
{
Thread.Sleep(TimeSpan.FromSeconds(5));
}
}
}
public void DoWork()
{
try
{
Task<int>[] _tempTaskList = new Task<int>[100];
for (int i = 0; i < 100; i++)
{
int localI = i;
_tempTaskList[localI] = Task.Run(() =>
{
Logger.SetLogWriter(new LogWriterFactory().Create(), false);
var logEntry = new LogEntry
{
Severity = TraceEventType.Information,
Message = "Job Started :",
};
logEntry.Categories.Clear();
logEntry.Categories.Add("Send.To.EventLog");
Logger.Write(logEntry);
return 0;
});
}
bool IsAnyTaskPending = true;
int noOfTasks = 0;
while (IsAnyTaskPending == true)
{
foreach (var t in _tempTaskList)
{
// Remove Completed Tasks from TaskList
if (t != null && t.Status == TaskStatus.RanToCompletion)
{
Task<int> completedTask = t;
var temp = _tempTaskList.ToList();
//temp.Remove(t);
//_tempTaskList = temp.ToArray();
noOfTasks++;
//Console.WriteLine(" Completed");
}
else if (t != null && t.Status == TaskStatus.Faulted)
{
Console.WriteLine(" Failed");
}
}
if (_tempTaskList.Length == 0)
{
IsAnyTaskPending = false;
Console.WriteLine("All {0} Tasks Done", noOfTasks);
}
}
IsWorkStarted = false;
}
catch(Exception e)
{
throw;
}
}
}
}
Il semble que vous ne pouvez pas avoir deux écrivains qui écrivent exactement au même moment dans le journal. Vous devrez peut-être synchroniser l'accès (comme vous l'avez découvert) pour éviter les conflits. En passant, beaucoup de ce que vous faites peut être fait avec des suites (complet ou échoué, etc) et «Task.WhenAll». –
Yeh semble comme ça ... Je ne veux pas faire Task.WhenAll parce que dans mon code de production, nous faisons quelque chose en surveillant le statut. – Zeus