My program was practice for me, however, when I try to write all the directories it found, it crashes.
I tried the following:
I cannot see why this wouldn't work, what have I done wrong?
static void Main(string[] args)
{
Method(@"C:\");
}
static void Method(string dir)
{
//crash happens here v
StreamWriter sw = new StreamWriter(@"C:\users\"+Environment.UserName+"\desktop\log.txt",true);
foreach (string subdir in Directory.GetDirectories(dir))
{
try
{
Console.WriteLine(subdir);
sw.Write(subdir);
Method(subdir);
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("Error");
}
}
sw.Close();
}
Its recursive.
Because you're calling Method
again here:
Console.WriteLine(subdir);
sw.Write(subdir);
Method(subdir); // BOOM
Your file is already open. You can't open it for writing again.
Open the file in Main
once..
static void Main(string[] args) {
using (StreamWriter sw = new StreamWriter(@"C:\users\"+Environment.UserName+"\desktop\log.txt",true)) {
Method(@"C:\", sw);
}
}
Then accept it in your method:
public static void Method(string dir, StreamWriter sw) {
Then when you call it again:
sw.Write(subdir);
Method(subdir, sw); // pass in the streamwriter.
Note though, that you will quickly start chewing up memory. You're recursing through your entire C:\ drive. Maybe test it on a smaller folder?
I am agree with above but in my case solution different a little.
private static object locker = new object();
private static void WriteMessageToFile(string message)
{
string dateStr = DateTime.Now.Date.Day.ToString()+"_"+ DateTime.Now.Date.Month.ToString()+"_"+ DateTime.Now.Date.Year.ToString();
if (!Directory.Exists("Logs"))
{
DirectoryInfo di = Directory.CreateDirectory("Logs");
}
//Guid guidGenerator = Guid.NewGuid();
string filePath = _env.ContentRootPath + "\\Logs\\ProcessLog_" + dateStr + ".txt";
FileInfo fi = new FileInfo(filePath);
lock (locker)
{
using (FileStream file = new FileStream(fi.FullName, FileMode.Append, FileAccess.Write, FileShare.Read))
using (StreamWriter streamWriter = new StreamWriter(file))
{
streamWriter.WriteLine(message);
streamWriter.Close();
}
}
}
Because the following function is called asynchronous and asynchronous in many places in my asp.net core application. In this case, one thread was trying to write a file, another thread wanted to write the same file, and there was an error. As a solution, I tried the above, but it didn't work either because I tried to open a new stream before closing the previous stream. So I decided to write a secure block of code as a solution. In this case, since the other threads could not reach the locked area, they made the write operation by waiting for the previous operation and I was able to write the file without error.
I think; there is another reason code behind, cause i have used Singleton registration on startup. This function's caller classes are isolated from each other. with this reason they didn't know which thread is called the function before. Their lifetime has been finished while. Also FileStream wraps the StreamWriter then it also may work without lock, anyway it is guaranty.
Even Microsoft.Extensions.Logging does not support FileLoger by default, but we can write custom. I share the entire implementation below
public class FileLoger : ILogger
{
public static IHostingEnvironment _env;
private static object locker = new object();
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
var message = string.Format("{0}: {1} - {2}", logLevel.ToString(), eventId.Id, formatter(state, exception));
WriteMessageToFile(message);
}
private static void WriteMessageToFile(string message)
{
string dateStr = DateTime.Now.Date.Day.ToString()+"_"+ DateTime.Now.Date.Month.ToString()+"_"+ DateTime.Now.Date.Year.ToString();
if (!Directory.Exists("Logs"))
{
DirectoryInfo di = Directory.CreateDirectory("Logs");
}
//Guid guidGenerator = Guid.NewGuid();
string filePath = _env.ContentRootPath + "\\Logs\\ProcessLog_" + dateStr + ".txt";
FileInfo fi = new FileInfo(filePath);
lock (locker)
{
using (FileStream file = new FileStream(fi.FullName, FileMode.Append, FileAccess.Write, FileShare.Read))
using (StreamWriter streamWriter = new StreamWriter(file))
{
streamWriter.WriteLine(message);
streamWriter.Close();
}
}
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return true;
}
}
public class FileLogProvider : ILoggerProvider
{
public FileLogProvider(IHostingEnvironment env)
{
FileLoger._env = env;
}
public ILogger CreateLogger(string category)
{
return new FileLoger();
}
public void Dispose()
{
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With