7 Replies - 1148 Views - Last Post: 25 August 2015 - 07:20 PM Rate Topic: -----

#1 Anthonidas   User is offline

  • D.I.C Head

Reputation: 32
  • View blog
  • Posts: 240
  • Joined: 25-April 11

How to logging from inside and outside of a ThreadPool

Posted 13 August 2015 - 08:27 AM

Hello Guys

I am wondering why a logging instance that I create in the main thread can be moved into a threadpool but can not be accessed again outside of the threadpool when the threadpool finishes its work...

i have the following piece of code:
Log.Logger logFile = new Log.Logger();
logFile.WriteLine("Bla bla bla"); // here it is working :)/>
.
.
.
using (ManualResetEvent resetEvent = new ManualResetEvent(false))
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(x =>
    {
        installService(x);
        resetEvent.Set();
    }));
    resetEvent.WaitOne();
}


now the threadpool is started with my method installService(x). In this method I am using the same instance of logFile.WriteLine(......) and it still works. But when the installService(x) finishes its work and everything goes back to the main thread, my logFile does not write to the file anymore (for example if i use logFile.WriteLine() on a button click).

I'm not sure about that, but I think it could be due to the fact, that I am using a thread safe BlockingCollection?
my code:
BlockingCollection<Param> bc = new BlockingCollection<Param>();
String LogFile;
bool LogActive = false;

// Constructor create the thread that wait for work on .GetConsumingEnumerable()
public Logger(string path = "")
{
	if (String.IsNullOrWhiteSpace(LogFile))
		CreateLogFile(path);

	Task.Factory.StartNew(() =>
	{
        foreach (Param p in bc.GetConsumingEnumerable())
		{
			if (!LogActive)
				continue;

			StreamWriter sw = new StreamWriter(LogFile, true);

			switch (p.Ltype)
			{
				case Log.Param.LogType.Info:
					const string LINE_MSG = "[{0}] {1}";
					sw.WriteLine(String.Format(LINE_MSG, LogTimeStamp(), p.Msg));
					break;
				case Log.Param.LogType.Warning:
					const string WARNING_MSG = "[{3}] * Warning {0} (Action {1} on {2})";
					sw.WriteLine(String.Format(WARNING_MSG, p.Msg, p.Action, p.Obj, LogTimeStamp()));
					break;
				case Log.Param.LogType.Error:
					const string ERROR_MSG = "[{3}] *** Error {0} (Action {1} on {2})";
					sw.WriteLine(String.Format(ERROR_MSG, p.Msg, p.Action, p.Obj, LogTimeStamp()));
					break;
				case Log.Param.LogType.SimpleError:
					const string ERROR_MSG_SIMPLE = "[{0}] *** Error {1}";
					sw.WriteLine(String.Format(ERROR_MSG_SIMPLE, LogTimeStamp(), p.Msg));
					break;
				default:
					sw.WriteLine(String.Format(LINE_MSG, LogTimeStamp(), p.Msg));
					break;
			}
			sw.Close();
		}
	});
}


Does the ThreadPool close my logFile instance when work finishes? Do I have to redefine the logFile as a new Log.Logger() somewhere??

(I am new to threading and do not have much experience with it. Sorry.)

Thanks to everyone that helps :)

Is This A Good Question/Topic? 0
  • +

Replies To: How to logging from inside and outside of a ThreadPool

#2 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7463
  • View blog
  • Posts: 25,113
  • Joined: 05-May 12

Re: How to logging from inside and outside of a ThreadPool

Posted 13 August 2015 - 09:04 AM

This doesn't answer your question, but it's worth exploring: Just use log4net.
Was This Post Helpful? 0
  • +
  • -

#3 Curtis Rutland   User is offline

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 5106
  • View blog
  • Posts: 9,283
  • Joined: 08-June 10

Re: How to logging from inside and outside of a ThreadPool

Posted 13 August 2015 - 09:21 AM

Or nlog. Or Enterprise Library. Basically, don't reinvent the wheel when it comes to something like logging, because there are more "gotchas" than you think there are, and the last thing you want to do is have your production application crash because of a logging issue that you didn't know about. The log frameworks have already encountered and handled most of these errors.

If there's one thing I never roll my own of, it's crypto. If there's two things, it's crypto and logging.
Was This Post Helpful? 0
  • +
  • -

#4 Anthonidas   User is offline

  • D.I.C Head

Reputation: 32
  • View blog
  • Posts: 240
  • Joined: 25-April 11

Re: How to logging from inside and outside of a ThreadPool

Posted 13 August 2015 - 10:02 AM

Thanks for your suggestions. In fact originally I wanted to use a third party logging system but there are reasons why i chose to do it on my own... my application is a standalone EXE and it should stay like that. Not that it is impossible to handle but it surely complicates the way to use it. So I don't want to include any dll's... just have my exe. ;)

This post has been edited by Anthonidas: 13 August 2015 - 10:03 AM

Was This Post Helpful? 0
  • +
  • -

#5 Curtis Rutland   User is offline

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 5106
  • View blog
  • Posts: 9,283
  • Joined: 08-June 10

Re: How to logging from inside and outside of a ThreadPool

Posted 13 August 2015 - 10:38 AM

Have you ever heard of a utility called "ILMerge"? It can take multiple .NET Assemblies and produce a single file. There's a separate executable called "ILMerge GUI" that makes it easier to use. I've actually used it for real purposes before. CRM 2011+ allows you to make plugins with C# assemblies, but they're stored in the database and there's no simple way to upload its dependencies. ILMerge was one of the options I used, and it works fine, it can even produce assemblies with Strong Names (always a pain to deal with). In the end, we simply GACed our dependencies on the server that was hosting CRM, but ILMerge is an option for you if you'd like to explore keeping using a 3rd party library.

I'll stop derailing your thread now. Sorry we got this far off topic.
Was This Post Helpful? 1
  • +
  • -

#6 Anthonidas   User is offline

  • D.I.C Head

Reputation: 32
  • View blog
  • Posts: 240
  • Joined: 25-April 11

Re: How to logging from inside and outside of a ThreadPool

Posted 13 August 2015 - 10:47 AM

lol yes you did :D

no, never heard of it... i'm going to test it. thanks for the hint.
Was This Post Helpful? 0
  • +
  • -

#7 Anthonidas   User is offline

  • D.I.C Head

Reputation: 32
  • View blog
  • Posts: 240
  • Joined: 25-April 11

Re: How to logging from inside and outside of a ThreadPool

Posted 25 August 2015 - 03:58 PM

Hey guys, me again...

I've started to use NLog and I have to admit, that I like it.

I installed the package, tested it a bit and it works well when I use the default configuration. But there is a problem when I don't want to use an external config file.

The wiki of the Nlog project explains how to configure everything programmatically but for any unknown reason it doesn't work in my case. Could you please have a look and perhaps you see why?

In my main method, just after the InitializeComponents(), i call the configuration method for my NLog implementation (I called it InitializeNLogConfig() ):
LoggingConfiguration logConfig = new LoggingConfiguration();
            
            // default logging
            var defaultLogTarget = new FileTarget();
            logConfig.AddTarget("file", defaultLogTarget);

            defaultLogTarget.FileName = "${basedir}/MyLogFile.log";
            defaultLogTarget.Layout = "[${longdate}] ${message}";

            // error logging
            var errorLogTarget = new FileTarget();
            logConfig.AddTarget("file", errorLogTarget);

            errorLogTarget.FileName = "${basedir}/ServiceInstall.log";
            errorLogTarget.Layout = "[${longdate}] ****** ${level} ******${newline}" +
                                    "Call Site: ${callsite}${newline}" +
                                    "Exception Type: ${exception:format=Type}${newline}" +
                                    "Exception Message: ${exception:format=Message}${newline}" +
                                    "Stack Trace: ${exception:format=StackTrace}${newline}" +
                                    "Additional Info: ${message}";

            // define rules
            var ruleDefault = new LoggingRule("default", LogLevel.Debug, defaultLogTarget);
            var ruleError = new LoggingRule("error", LogLevel.Error, errorLogTarget);
            
            ruleDefault.EnableLoggingForLevel(LogLevel.Trace);
            ruleError.EnableLoggingForLevel(LogLevel.Error);

            logConfig.LoggingRules.Add(ruleDefault);
            logConfig.LoggingRules.Add(ruleError);

            // activate configuration
            LogManager.Configuration = logConfig;
            LogManager.ReconfigExistingLoggers();

            logFile = LogManager.GetCurrentClassLogger();
            staticLogFile = LogManager.GetCurrentClassLogger();

            Logger templog = LogManager.GetCurrentClassLogger();
            templog.Debug("Hello World");
            // at that point i can't find any logfile! why?


Was This Post Helpful? 0
  • +
  • -

#8 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7463
  • View blog
  • Posts: 25,113
  • Joined: 05-May 12

Re: How to logging from inside and outside of a ThreadPool

Posted 25 August 2015 - 07:20 PM

I don't use NLog, but I was just scanning your code and comparing to NLog's tutorial for using the configuration API. What stands out to me are line 23 and 24. Unless your lines 36-41 live in classes named "default" and "error", I wouldn't expect to see any log output either. Remember that loggers are tied to the class names.

Quote

It is important to understand that Logger does not represent any particular log output (and thus is never tied to a particular log file, etc.) but is only a source, which typically corresponds to a class in your code.

from "Creating Log message" section of Tutorial.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1