2015-10-17 16 views
0

下面是一个示例程序(您将需要Enterprise库来运行它)。我在循环中运行100个任务,他们将一些消息记录到事件日志中。我将生成的任务存储在任务数组中,并在一个while循环内简单地监视它。在任务循环中获取处置对象EnterpriseLibrary LogWriter错误

问题是100,随机任务失败,并给出以下错误。从我的理解任务有他们自己的状态,所以他们不应该互相干扰和记录器方法是静态的,所以我不知道我的对象被放置在哪里。

  1. 为什么Logger对象被放置,如果它的静态?

  2. 如果我把LOCK(对象)放在Task.Run()内部的记录器代码中,它可以正常工作。这是一个好主意吗 ?

错误

在Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter.get_SyncLock() 在Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter.ExecuteReadOperation(动作readOperation) 微软(LogEntry日志) (位于c:\ tfs \ Report \ Log.log中)中的WW.Test.TasksLoggingTest.b__1(LogEntry日志) (日志记录日志) (位于Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write WWTest \ TasksLoggingTest.cs:第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; 
      } 
     } 
    } 
} 
+1

看来你不可能有两个作家完全同时写入日志。您可能需要同步访问权限(正如您发现的那样)以避免争用。顺便说一句,你正在做的很多事情都可以通过延续(完成或失败等)和Task.WhenAll来完成。 –

+0

叶似乎是这样......我不想做Task.WhenAll,因为在我的生产代码中,我们通过监视状态来做某件事。 – Zeus

回答

2

问题是Logger.SetLogWriter被称为每个任务。内部LogWriter是一个单身人士。然而,当你调用SetLogWriter当前内部LogWriter配置:

public static void SetLogWriter(LogWriter logWriter, bool throwIfSet = true) 
    { 
     Guard.ArgumentNotNull(logWriter, "logWriter"); 

     var currentWriter = writer; 
     if (currentWriter != null && throwIfSet) 
     { 
      throw new InvalidOperationException(Resources.ExceptionLogWriterAlreadySet); 
     } 

     writer = logWriter; 

     if (currentWriter != null) 
     { 
      currentWriter.Dispose(); 
     } 
    } 

因此,每个任务配置的单LogWriter这是从下一些其他任务了拉动地毯。解决的办法是在调用任务之前提升一次SetLogWriter

+0

嗨兰迪,你能否进一步解释。 Bootstrap SetLogWriter是什么意思? – Zeus

+0

这是执行引导的代码:'Logger.SetLogWriter(new LogWriterFactory()。Create(),false);'。将此代码移至“开始”方法的开头,而不是将其放入线程中。 –

相关问题