所以我有一个循环的任务,一切正常并且正确记录
但是在我放了一个Parallel.ForEach
后,我的日志记录就被破坏了。
我有一个自定义跟踪侦听器,它接收跟踪消息并将int放入一个已处理的缓冲区以及记录。
并行后,不再调用跟踪侦听器。 (输出行是Trace.WriteLine的包装,并添加了trace和flush内容以试图解决问题.Trace.AutoFlush已经= true ...)
代码中的测试代码
Parallel.ForEach( allStudentsInAd, ( StudentPortalNightly.CV.AllAdStudentsCV adStudent ) =>
{
OutputLine( "*********before" );
//AddUserToListIfNotCorrectlyTied( allStudentsInCdssDict, studentsAlreadyTiedDict, adStudent, ref cachedAllStudentsToBeTied, ref allStudentsInAd );
OutputLine( "*********after" );
Trace.Flush();
});
每个请求并行化之前的代码(它是一个foreach)
foreach ( StudentPortalNightly.CV.AllAdStudentsCV adStudent in allStudentsInAd )
{
AddUserToListIfNotCorrectlyTied( allStudentsInCdssDict, studentsAlreadyTiedDict, adStudent, ref cachedAllStudentsToBeTied, ref allStudentsInAd );
}
听者
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using JCDCHelper.Extension;
using JCDCHelper.Logging.Interfaces;
using JCDCHelper.Utilities.Interfaces;
using StructureMap;
namespace StudentPortalNightly.Utilities
{
public class SpnCustomListener:TextWriterTraceListener
{
private INetLog log = ObjectFactory.GetInstance< INetLog >();
private Object slLock = new Object();
private List < string > sl = null;
/// <summary>
/// Sets the string list.
/// </summary>
/// <param name="_sl">The _SL.</param>
public void SetStringList( List<string> _sl )
{
sl = _sl;
}
/// <summary>
/// Gets the string list.
/// </summary>
/// <returns></returns>
public List<string> GetStringList()
{
return sl;
}
/// <summary>
/// Initializes a new instance of the <see cref="SpnCustomListener"/> class.
/// </summary>
public SpnCustomListener()
{
base.Name = "TraceOutputCustom.txt";
}
/// <summary>
/// Writes the value of the object's <see cref="M:System.Object.ToString"/> method to the listener you create when you implement the <see cref="T:System.Diagnostics.TraceListener"/> class, followed by a line terminator.
/// </summary>
/// <param name="o">An <see cref="T:System.Object"/> whose fully qualified class name you want to write.</param>
public override void WriteLine( object o )
{
WriteLine( o == null ? "" : o.ToString() );
}
/// <summary>
/// Writes a message to this instance's <see cref="P:System.Diagnostics.TextWriterTraceListener.Writer"/> followed by a line terminator. The default line terminator is a carriage return followed by a line feed (\r\n).
/// </summary>
/// <param name="message">A message to write.</param>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
/// </PermissionSet>
public override void WriteLine( string message )
{
log.Debug("WriteLine()..."+ message );
message = DateTime.Now.ToString() + " " + message;
//base.Write( " " );
base.WriteLine( message );
if ( null != sl )
{
lock( slLock )
{
sl.Add( message );
}
Console.WriteLine( message );// so it will log in console mode too - EWB
}
else
{
log.Debug( "SpnCustomListener string buffer is null" );
}
}
}
}
它们都是作为Threadlocal创建的吗?
我需要做些什么才能让各个线程登录到跟踪侦听器?
答案 0 :(得分:1)
很难说,因为根据您发布的代码,无法确定您的收听者可能会被调用的位置。但是,您遇到的一个问题是:
public class SpnCustomListener:TextWriterTraceListener
{
private INetLog log = ObjectFactory.GetInstance< INetLog >();
private Object slLock = new Object();
private List <string> sl = null;
因为您的slLock
对象是私有的,所以它将在每个类的实例中创建,因此它不会跨线程工作;试试这个:
public class SpnCustomListener:TextWriterTraceListener
{
private INetLog log = ObjectFactory.GetInstance< INetLog >();
private static Object slLock = new Object();
private List <string> sl = null;