I need to write a file that is located on a remote directory. I need to create a log application: every time an error occurs, I want to access this remote file and write a line. But if the remote directory is not available, I don't care. I simply want the main application keep running.
Usually accessing this remote directory takes 1 second. If the WriteLine method takes more than 1 second, I want to block it.
I tried with a try catch but then the entire application is blocked for a long time. I need to interrupt this attempt to write sooner.
This is the main code used to write on the txt file:
try
{
string TargetFile = "F:\\file.txt";
using (StreamWriter sw = File.AppendText(TargetFile))
{
sw.WriteLine("LOG: an error occured\n");
sw.Close();
}
}
catch (Exception)
{
throw;
}
I can't figure out how to solve this problem. Maybe by running the write operation inside a separate thread? Thanks for your help!
1) do not throw inside catch block
2) use managed threads to speed up the process and increase performance
If you are using .Net 4.5 and above the block i have written below will help. Just add this in your program
using System.Threading.Tasks;
var errorWriter = Task.Run(() =>
{
try
{
string TargetFile = "F:\\file.txt";
using (StreamWriter sw = File.AppendText(TargetFile))
{
sw.WriteLine("LOG: an error occured\n");
sw.Close();
return "success";
}
}
catch (Exception ex)
{
return ex.Message;
// throw; _________________ don't throw here
}
});
Related
I have following code.
try
{
int s=10;
int k=0;
int stdsd = s / k;
}
catch (DivideByZeroException ext)
{
FileStream fs = new FileStream(#"C:\temp\data.txt", FileMode.Open);
//encountered an exception as file doesn't exist.
}
catch (Exception ex)
{
}
finally
{
//some code here.
}
In above code when exception occured then it will try to write that in one file in catch block.but when it trying to open that file that file doen't exists, so in such cases system crashed. I want to execute such critical code in finally block but due to exception in catch block it not going further to that line.
I know we can check file exists check but I don't want to check file exist check over here, I want to how to manage that in catch block.
can please assist the best way to manage exception in catch block.
You can't handle the exception generated from one catch block in a catch block associated with the same try/catch statement. Instead, you need an extra one:
catch (DivideByZeroException ext)
{
try
{
FileStream fs = new FileStream(#"C:\temp\data.txt", FileMode.Open);
}
catch (IOException e)
{
// Handle the exception here
}
}
Note that you should be using a using statement when opening the stream, so that you'll close it automatically whether or not an exception is thrown later.
I'd also recommend not having the code like this in the catch block directly - typically catch blocks should be short, for readability. Consider moving all the error-handling functionality into a separate method (or possibly even a separate class).
Just use another try {} catch {} ...
try {
// ...
try {
// try opening your file here ...
} catch (Exception) {
// ...
}
} catch (Exception) {
// ...
}
If you don't want to check the existence of the file "over here" (in the exception), then you could alternatively check the existence "over there", that is: earlier in the code.
What you want to do is to write an exception log to a file, as I understand it. So you could configure the correct log file handling earlier in the code, in the best case with a good log file handler. After this the only thing you have to do within the exception handler is to push your exception message to the log handler - which will then write this information properly to the file.
exceptions are very powerful future of any language that can not be ignored in most cases , but try to avoid it if possible
Look at this
String File = "File.txt";
System.IO.FileInfo fileinfo = new System.IO.FileInfo(File);
if(fileinfo.Exists)
{
using (System.IO.FileStream file = new System.IO.FileStream(File, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite))
{
// operation on file here
}
}else
{
using (System.IO.FileStream file = new System.IO.FileStream(File, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite))
{
// operation on file here now the file is new file
}
}
This question already has answers here:
Why is try {...} finally {...} good; try {...} catch{} bad?
(20 answers)
Closed 9 years ago.
difference between try...catch and try....finally ? in asp.net(C#)
like when i want to catch error like 1/0 then i put code in try block and put exception object in catch block like response.write("ERROR:"+ ex.Message) but advisors told me that it isn't a good practice to put catch always, it absorbs error without notifying ????? ehhhhh ? but it did via ex.Message , so why ?
and what does try....finally do ? i know that it is used to release resources but of what use is TRY if exception can't be catched ?
try/catch/finally:
try
{
// open some file or connection
// do some work that could cause exception
}
catch(MyException ex)
{
// do some exception handling: rethrow with a message, log the error, etc...
// it is not a good practice to just catch and do nothing (swallow the exception)
}
finally
{
// do some cleanup to close file/connection
// guaranteed to run even if an exception happened in try block
// if there was no finally, and exception happened before cleanup in your try block, file could stay open.
}
Try/Finally:
try
{
// open some file/connection
// do some work, where you're not expecting an exception
// or, you don't want to handle the exception here, rather just let it go to the caller, so no need for a catch
}
finally
{
// do cleanup, guaranteed to go in this finally block
}
Eveything that is enclosed in your finally block is ensured to be executed, and it could be useful in these 2 concrete cases at least :
Sometimes you decide to call return in the middle of your try block and get back to the caller : finally ease the process of releasing ressources here, you don't have to write some specific code to go directly to the end of your method.
Sometimes you want to let an exception go up (by not catching it) and maybe being caught at a higher level (because it is not the appropriate place to handle it properly for example). Again finally ensures your resources are released and the exception continue its path.
Maybe you can see finally as a tool helping developpers to do things they're obliged to do with less effort. On the other side, catch is dedicated to handle errors.
Both keywords are dedicated to flow control, but they don't have the same purpose and they can be used one without each other (and often are!). It depends on your needs.
Finally is always executed whether there is an exception or not. This can be handy if you want to be absolutely certain that something is cleaned up. Example:
void ReadFile(int index)
{
// To run this code, substitute a valid path from your local machine
string path = #"c:\users\public\test.txt";
System.IO.StreamReader file = new System.IO.StreamReader(path);
char[] buffer = new char[10];
try
{
file.ReadBlock(buffer, index, buffer.Length);
}
catch (System.IO.IOException e)
{
Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message);
}
finally
{
if (file != null)
{
file.Close();
}
}
// Do something with buffer...
}
If you didn't have a finally in there it would be possible that the file would not be closed properly if an error occurred. Regardless of whether an error occurs or not, you want the file to be closed when you are done.
Consider the alternative:
void ReadFile(int index)
{
// To run this code, substitute a valid path from your local machine
string path = #"c:\users\public\test.txt";
System.IO.StreamReader file = new System.IO.StreamReader(path);
char[] buffer = new char[10];
try
{
file.ReadBlock(buffer, index, buffer.Length);
file.Close();
}
catch (System.IO.IOException e)
{
Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message);
}
}
If you error out on ReadBlock the file will not be properly closed.
When a file is being copied to the file watcher folder, how can I identify whether the file is completely copied and ready to use? Because I am getting multiple events during file copy. (The file is copied via another program using File.Copy.)
When I ran into this problem, the best solution I came up with was to continually try to get an exclusive lock on the file; while the file is being written, the locking attempt will fail, essentially the method in this answer. Once the file isn't being written to any more, the lock will succeed.
Unfortunately, the only way to do that is to wrap a try/catch around opening the file, which makes me cringe - having to use try/catch is always painful. There just doesn't seem to be any way around that, though, so it's what I ended up using.
Modifying the code in that answer does the trick, so I ended up using something like this:
private void WaitForFile(FileInfo file)
{
FileStream stream = null;
bool FileReady = false;
while(!FileReady)
{
try
{
using(stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
FileReady = true;
}
}
catch (IOException)
{
//File isn't ready yet, so we need to keep on waiting until it is.
}
//We'll want to wait a bit between polls, if the file isn't ready.
if(!FileReady) Thread.Sleep(1000);
}
}
Here is a method that will retry file access up to X number of times, with a Sleep between tries. If it never gets access, the application moves on:
private static bool GetIdleFile(string path)
{
var fileIdle = false;
const int MaximumAttemptsAllowed = 30;
var attemptsMade = 0;
while (!fileIdle && attemptsMade <= MaximumAttemptsAllowed)
{
try
{
using (File.Open(path, FileMode.Open, FileAccess.ReadWrite))
{
fileIdle = true;
}
}
catch
{
attemptsMade++;
Thread.Sleep(100);
}
}
return fileIdle;
}
It can be used like this:
private void WatcherOnCreated(object sender, FileSystemEventArgs e)
{
if (GetIdleFile(e.FullPath))
{
// Do something like...
foreach (var line in File.ReadAllLines(e.FullPath))
{
// Do more...
}
}
}
I had this problem when writing a file. I got events before the file was fully written and closed.
The solution is to use a temporary filename and rename the file once finished. Then watch for the file rename event instead of file creation or change event.
Note: this problem is not solvable in generic case. Without prior knowledge about file usage you can't know if other program(s) finished operation with the file.
In your particular case you should be able to figure out what operations File.Copy consist of.
Most likely destination file is locked during whole operation. In this case you should be able to simply try to open file and handle "sharing mode violation" exception.
You can also wait for some time... - very unreliable option, but if you know size range of files you may be able to have reasonable delay to let Copy to finish.
You can also "invent" some sort of transaction system - i.e. create another file like "destination_file_name.COPYLOCK" which program that copies file would create before copying "destination_file_name" and delete afterward.
private Stream ReadWhenAvailable(FileInfo finfo, TimeSpan? ts = null) => Task.Run(() =>
{
ts = ts == null ? new TimeSpan(long.MaxValue) : ts;
var start = DateTime.Now;
while (DateTime.Now - start < ts)
{
Thread.Sleep(200);
try
{
return new FileStream(finfo.FullName, FileMode.Open);
}
catch { }
}
return null;
})
.Result;
...of course, you can modify aspects of this to suit your needs.
One possible solution (It worked in my case) is to use the Change event. You can log in the create event the name of the file just created and then catch the change event and verify if the file was just created. When I manipulated the file in the change event it didn't throw me the error "File is in use"
If you are doing some sort of inter-process communication, as I do, you may want to consider this solution:
App A writes the file you are interested in, eg "Data.csv"
When done, app A writes a 2nd file, eg. "Data.confirmed"
In your C# app B make the FileWatcher listen to "*.confirmed" files. When you get this event you can safely read "Data.csv", as it is already completed by app A.
(Edit: inspired by commets) Delete the *.confirmed filed with app B when done processing the "Data.csv" file.
I have solved this issue with two features:
Implement the MemoryCache pattern seen in this question: A robust solution for FileSystemWatcher firing events multiple times
Implement a try\catch loop with a timeout for access
You need to collect average copy times in your environment and set the memory cache timeout to be at least as long as the shortest lock time on a new file. This eliminates duplicates in your processing directive and allows some time for the copy to finish. You will have much better success on first try, which means less time spent in the try\catch loop.
Here is an example of the try\catch loop:
public static IEnumerable<string> GetFileLines(string theFile)
{
DateTime startTime = DateTime.Now;
TimeSpan timeOut = TimeSpan.FromSeconds(TimeoutSeconds);
TimeSpan timePassed;
do
{
try
{
return File.ReadLines(theFile);
}
catch (FileNotFoundException ex)
{
EventLog.WriteEntry(ProgramName, "File not found: " + theFile, EventLogEntryType.Warning, ex.HResult);
return null;
}
catch (PathTooLongException ex)
{
EventLog.WriteEntry(ProgramName, "Path too long: " + theFile, EventLogEntryType.Warning, ex.HResult);
return null;
}
catch (DirectoryNotFoundException ex)
{
EventLog.WriteEntry(ProgramName, "Directory not found: " + theFile, EventLogEntryType.Warning, ex.HResult);
return null;
}
catch (Exception ex)
{
// We swallow all other exceptions here so we can try again
EventLog.WriteEntry(ProgramName, ex.Message, EventLogEntryType.Warning, ex.HResult);
}
Task.Delay(777).Wait();
timePassed = DateTime.Now.Subtract(startTime);
}
while (timePassed < timeOut);
EventLog.WriteEntry(ProgramName, "Timeout after waiting " + timePassed.ToString() + " seconds to read " + theFile, EventLogEntryType.Warning, 258);
return null;
}
Where TimeoutSeconds is a setting that you can put wherever you hold your settings. This can be tuned for your environment.
I would like ask you to explain me how the exception system works in the following piece of code:
static void Main(string[] args)
{
try
{
//Code which throws exceptions from time to time and runs in a loop
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
}
I noticed something which surprised me. When an exception is thrown, the code inside try{...} block is still running and can throw even more exceptions which will be printed to the console window.
Shouldn't the code inside the loop finish its execution and "jump" to Console.ReadKey() at the end?
#EDIT:
The code inside is complicated and it would take a few pages. I can tell you that I make multiple asynchronous operations inside like downloading files, receiving packets, etc. In other words there are other threads which are created in the loop.
#EDIT2:
Presumably this is the code responsible for the behavior:
public SomeConstructor(Socket server)
{
_pb = new PacketBuilder(server, c);
SocketWrapper sw = new SocketWrapper(server, Globals.recvBufferSize);
sw.Socket.BeginReceive(sw.Buffer, 0, Globals.recvBufferSize, SocketFlags.None,PacketReceiveCallback, sw);
_pi = new PacketInterpreter(this, c);
}
private void PacketReceiveCallback(IAsyncResult iar)
{
SocketWrapper sw = iar.AsyncState as SocketWrapper;
int bytesReceived = sw.Socket.EndReceive(iar);
_pi.Interpret(sw.Buffer, 0, bytesReceived);
if (bytesReceived > 0)
sw.Socket.BeginReceive(sw.Buffer, 0, Globals.recvBufferSize, SocketFlags.None, PacketReceiveCallback, sw);
}
Code inside try block will execute as long as it doesn't throw an exception. If the exception throw within your try block the following code will not execute and it will jump to catch block.
static void Main(string[] args)
{
try
{
//Code which throws exceptions from time to time and runs in a loop
Console.WriteLine("Line 1");
throw new Exception("Sample Exception"); // your code will stop here and following line will not prine.
Console.WriteLine("This line will not print");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
}
The only reason I can think of why you would get such a behavior is if you're starting new threads inside your try block. So if you're starting any new threads or using the task parallell library or plinq, you might get something like that.
But it's really hard to inspection-debug code that was replaced by a comment...
Simple best practice question.
Should you nest try catch statements or just use methods.
For instance, if you have a method that opens a file does work and closes the file, you would have the open and close outside the try catch, or rather the close in the finally block.
Now if your open method fails, the method would assert right? So should your wrap that in a try catch block or should that be called from another method, which in turn as a try catch block?
In the context of a method that opens a file I would use a using statement vs a try catch. The using statement ensures that Dispose is called if an exception occurs.
using (FileStream fs = new FileStream(file, FileMode.Open))
{
//do stuff
}
does the same thing as:
FileStream fs;
try
{
fs = new FileStream(file, FileMode.Open);
//do Stuff
}
finally
{
if(fs!=null)
fs.Dispose();
}
Now that we have lambdas and type inference and some other stuff, there's an idiom that is common in other languages which now makes a lot of sense in C#. Your example was about opening a file, doing something to it, and then closing it. Well, now, you can make a helper method which opens a file, and also takes care of making sure to close / dispose / clean up, but calls out to a lambda you provide for the "do stuff" portion. This will help you get the complicated try/catch/finally dispose/cleanup stuff right in one place, and then use it over and over.
Here's an example:
public static void ProcessFile(string filePath, Action<File> fileProcessor)
{
File openFile = null;
try
{
openFile = File.Open(filePath); // I'm making this up ... point is you are acquiring a resource that needs to be cleaned up after.
fileProcessor(openFile);
}
finally
{
openFile.Close(); // Or dispose, or whatever.
}
}
Now, callers of this method don't have to worry about how to open the file or close / dispose of it. They can do something like this:
Helpers.ProcessFile("C://somefile.txt", f =>
{
while(var text = f.ReadLine())
{
Console.WriteLine(text);
}
});
This is a style question but for me I try to never have more than one level of try/catch/finally nesting in a single method. At the point you hit a nested try, you've almost certainly violated the 1 function = 1 operation principal and should use a second method.
Depends on what you are trying to do, but in most cases, nested try/catches are a sign of an over-complex function (or of a programmer who doesn't quite know how exceptions work!).
In the case of the open file, I'd use an IDisposable holder and a using clause, and so forgo the need of any explicit try/catch.
How about where you have related code that doesn't necessarily belong in a separate function of it's own right? Would this then be correct?
try
{
// Part 1 Code Here
try
{
// Part 2 Code Here
}
catch (Exception ex)
{
// Error from Part 2
}
}
catch (Exception ex)
{
// Error from Part 1
}
Most of the time I would break up the nested try/catch blocks into functions. But I have sometimes written code to catch and log all uncaught exceptions thrown by my application. But what if the logging code fails? So I have yet another try/catch around that just to prevent the user from seeing the default .NET unhandled exception dialog box. But even this code could very easily be refactored into functions instead of nested try/catch blocks.
try
{
try
{
DoEverything();
}
catch (Exception ex)
{
// Log the exception here
}
}
catch (Exception ex)
{
// Wow, even the log is broken ...
}
//create a switch here and set it to 0
try
{
DoChunk1();
//looks good. set the switch to 1
}
catch (Exception ex)
{
// Log the exception here
}
// check the switch, if it is still zero at this point then you may halt your program here; else set the switch back to zero and execute your next try catch statement. totally agree with breaking them down as mentioned above
try
{
DoChunk2();
//looks good. set the switch to 1
}
catch (Exception ex)
{
// Log the exception here
}
try
{
----
}
catch
{
try
{
---
}
catch
{
---
}
}