2
I have an application (which is a Windows service) that currently runs N Threads. What I want to do is capture whichever error that occurs in the application to write to a log file '.txt'. Only I want to do it so global.
I’m wearing the event FirstChanceException, only that this event executes only by Appdomain and if only to register the event in the main thread of the application, all errors would be recorded in a single file '.txt', causing a lot of competition and etc.
So I thought I’d create several Appdomains (each AppDomain with one of those Threads I have in the app) to capture exceptions of each Thread. I made a test application and it works: at the end I have a log file for each Thread.
Only my doubts are:
- Is this the best way to globally capture exceptions in N Threads applications? Would you have another way to do this?
- Creating an Appdomain for each Thread will not generate any process overload in S.O.?
- If you crash Firstchanceexception, you will get an endless loop of errors. Especially if you write in text file. Would have some Firstchanceexpception alternative?
Research I’ve already done: https://docs.microsoft.com/pt-br/dotnet/framework/app-domains/application-domains?view=netframework-4.8
https://stackoverflow.com/questions/5569580/exceptions-in-multithreaded-application/43934857
Below follows what I did for testing:
public class Program
{
private static ReaderWriterLockSlim lock_ = new ReaderWriterLockSlim();
public static void Main(string[] args)
{
try
{
AppDomain.CurrentDomain.FirstChanceException += (object sender, FirstChanceExceptionEventArgs e) =>
{
GravarLog(e.Exception);
};
AppDomain domain1 = AppDomain.CreateDomain("Consumidor-1");
domain1.FirstChanceException += (object sender, FirstChanceExceptionEventArgs e) =>
{
GravarLog(e.Exception);
};
Consumer consumer1 = (Consumer)domain1.CreateInstanceAndUnwrap(
typeof(Consumer).Assembly.FullName,
typeof(Consumer).FullName);
consumer1.Iniciar();
AppDomain domain2 = AppDomain.CreateDomain("Consumidor-2");
domain2.FirstChanceException += (object source, FirstChanceExceptionEventArgs e) =>
{
GravarLog(e.Exception);
};
Consumer consumer2 = (Consumer)domain2.CreateInstanceAndUnwrap(
typeof(Consumer).Assembly.FullName,
typeof(Consumer).FullName);
consumer2.Iniciar();
}
catch (Exception ex)
{
throw;
}
Console.ReadLine();
}
private static void GravarLog(Exception exception)
{
lock_.EnterWriteLock();
try
{
File.AppendAllText($"D:\\Temp\\Log\\Thread-{Thread.GetDomainID()}-error.txt",
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ff") + " - " +
$@"{AppDomain.CurrentDomain.FriendlyName} -> FirstChanceException: {exception.Message}");
}
finally
{
lock_.ExitWriteLock();
}
}
}
public class Consumer : MarshalByRefObject
{
public void Iniciar()
{
var tarefa = new Thread(() =>
{
int contador = 1;
while (true)
{
contador++;
var resultado = VerificarRegras();
Thread.Sleep(10000);
}
});
tarefa.Start();
}
public string VerificarRegras()
{
string regraNegocio = "Tudo OK!";
try
{
throw new ArgumentException("Thrown Exception" + Environment.NewLine);
}
catch
{
regraNegocio = "A validação da regra retornou...";
}
return regraNegocio;
}
}
Because your work of
Threadsis not managed by a common class, where in this class there are exceptions management? Imagine a classThreadManagerthat possesses an objectThread. You can make this class receive oneAction, where theconstructorclass would receive this action. A private function with the name, for example,DoWork()(example) would invoke thisActionwith a global Try-catch. The log is generated based on theThreadId. And instead of you spawnar Nthreads, you spawna N managersthread.– Kevin Kouketsu
You may even have other things to do that might make your solution better, but you could only tell by knowing the case. Why do I wonder why N threads, for example
– Kevin Kouketsu
@Kevinkouketsu actually has 42 threads in the app today, but this number can go up. What happens: the application processes messages that were sent by the middleware Rabbitmq. Each Thread is a
Consumidor/Assinanteof a queue of messages in Rabbitmq, and has the task of receiving and processing each message. In fact each Thread represents a "task/process" to process message. If instead of each thread a process was created, it would have all the operating system scheduling and in the Windows task manager would appear 42 ". exe". So I opted for Threads.– Raquel Pinheiro