i have an object that is being accessed by 2 events simulataneously.
first, a user-defined event will access it, then the projectItemsEvent_ItemAdded event, opens it again.
and got this error "The process cannot access the file because it is being used by another process."
please help!
thanks
Code Example:
void ProjectItemEvents_ItemAdded()
{
Util util = new Util(_applicationObject.Solution, CurrentSelectedProject)
if (name != null)
{
util.AddNewObject();
}
}
void addItem(object sender, WebReferenceEventArgs e)
{
try
{
System.Threading.Thread.Sleep(4500);
Util util = new Util(_applicationObject.Solution, CurrentSelectedProject)
util.AddNewObject();
}
catch (Exception ex)
{
}
}
It sounds like you're opening a file in both of the event handlers (hard to say for sure without code examples).
If you're just reading the file (rather than modifying/overwriting it), you could open it for shared access and allow multiple processes to have the same file open.
FileInfo fi = new FileInfo(#"C:\someFile.txt");
FileStream fs = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
If you post some code snippets, we might be able to help you integrate the change into what you already have.
UPDATE
After looking at your code, my guess is that there is a File Acess problem inside of the Util class. Can you also post its constructor?
You should probably use the lock keyword, if there is no way for you to avoid the events from colliding.
http://msdn.microsoft.com/en-us/library/c5kehkcz(VS.80).aspx
http://www.toolazy.me.uk/template.php?content=lock(this)_causes_deadlocks.xml
You have to make sure to close the FileStream after you finish reading the file.
FileStream.Close();
Related
I am doing a simple test in code, as follows:
try
{
File.Open(path);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
path is a string declared above. This routine is called when a button is pressed, and the first time it is called, it "works normally" (in quote, because although it doesn't throw an exception, the file is never open/shown). The second time it is pressed, the following exception is thrown:
System.IO.IOException: The process cannot access the file because it is being used by another process.
However, the file is actually never open. I monitor it with Task Manager, and no instance of the file is ever exhibited.
I tried using using (File.Open(path)) {}, but to no success.
Can anybody help me? It seems like a basic mistake I'm doing, but I can't find it.
UPDATE
Lasse Vågsæther Karlsen provided the correct answer, pointing out that my mistake was actually about the concept, not the code. Thanks!
I think you've misunderstood what File.Open does.
This method will open the file for reading by your program. In other words, that method will return a Stream object which you can use to read from and write to that file.
At the end of that operation, you have to close it, which is what using would do for you.
However, I'm guessing that this is not what you want to do. You keep mentioning that the file does not open, and that you're using the Task Manager to look for the file, not seeing it.
You want Process.Start instead. You're trying to open either another executable, such as notepad.exe, or you're trying to open a document, like readme.txt, that's why you're not using the result of calling that method, and why you're using the Task Manager to look for it.
So, assuming you still want to catch exceptions, this is what you should do:
try
{
Process.Start(path);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
I want to encapsulate the process of unzipping a zip file, making the files available for use, and then automatically cleaning them up when they are no longer needed. I did this with a class that implements the IDisposable interface, so that I can instantiate it with "using" and the files will be cleaned up when going out of scope, eliminating the need to specifically delete the files. The class, TempUnzip, can therefore be used thus:
static void AccessZipFileContents(string zipFilePath)
{
using (var temp = new TempUnzip(zipFilePath)
{
var tempPath = temp.TempPath;
if (tempPath != null)
{
// read/use the files in tempPath
}
} // files automatically get deleted when it goes out of scope! Woohoo!
}
Here is the implementation of the TempUnzip class:
using System.IO;
using System.IO.Compression;
public class TempUnzip : IDisposable
{
public TempUnzip(string zipFilePath)
{
try
{
var tempFolderName = Path.GetRandomFileName();
var tempFolder = Path.GetTempPath();
var tempPath = Path.Combine(tempFolder, tempFolderName);
Directory.CreateDirectory(tempPath);
ZipFile.ExtractToDirectory(zipFilePath, tempPath);
TempPath = tempPath;
}
catch (Exception) { TempPath = null; }
}
public readonly string TempPath;
public void Dispose()
{
try
{
if (TempPath != null)
Directory.Delete(TempPath);
}
catch (Exception) { }
}
}
Is this a valid use of IDisposable?
If so, do I need to implement the full standard IDisposable pattern?
If not, is there a better way to encapsulate the creation and destruction of files in such a way that they're tied to the lifetime of an object, or should I avoid this altogether?
Is this a valid use of IDisposable?
From the documentation:
Provides a mechanism for releasing unmanaged resources.
Files on local disk are certainly unmanaged resources. Thus, this use fits with the stated purpose of IDisposable.
If so, do I need to implement the full standard IDisposable pattern?
You can. The usual cautions about finalizers need to be considered, but you already linked to those. It certainly won't hurt.
If not, is there a better way to encapsulate the creation and destruction of files in such a way that they're tied to the lifetime of an object, or should I avoid this altogether?
I also like a functional approach for this kind of problem. That would make your example look something like this:
static void AccessZipFileContents(string zipFilePath)
{
ZipManager.RunWithZipExtracted(zipFilePath, (string tempPath) =>
{
if (tempPath != null)
{
// read/use the files in tempPath
}
} // files automatically get deleted when it goes out of scope! Woohoo!
}
//from ZipManager.cs...
static void RunWithZipExtracted(string zipLocation, Action<string> toRun)
{
var tempPath = CalculateTempPath();
try
{
ExtractZip(zipLocation, tempPath);
toRun(tempPath);
}
finally
{
DeleteFolder(tempPath);
}
} //private methods left as exercise for the reader
A pattern like that avoids the problem of "what if they don't call Dispose?" entirely.
This is a situation where having a finalizer is probably a good idea, but the MS pattern is predicated on the idea of public objects having finalizers, which is almost always a bad idea. Instead, resources that will require finalization-based cleanup should be encapsulated in privately-held objects whose references are never exposed to the outside world. Because the inner objects are private, there's no need for them to use the IDisposable pattern--instead they may be designed in whatever fashion best fits the requirement.
Since trying to close a file handle more than once may have catastrophic consequences, and it's possible (though rare) for a finalizer to execute while other code is using an object (or even performing Dispose upon it!), writing a robust class can be difficult. A nasty issue that arises is that file accesses can block but finalizer actions shouldn't. One could work around that by creating a thread whose purpose was to wait until the file is supposed to be closed and deleted, and which would then close and delete the file. Even if the attempt to delete the file gets blocked, other finalizer actions could continue apace. Unfortunately, eagerly creating a thread for the purpose of allowing safe finalizer-based cleanup is apt to be a waste of resources, but thread creation seems like an excessively-heavyweight task to be performing within a finalizer. I don't know what the best solution is.
In this instance I would say that it is a good example of IDisposable, if Dispose isn't called straight away that you've finished using it then it's not the end of the world and quickly calling this for the same zip file wouldn't cause an exception as you're using unique temp folders each time; which again you're not leaving file pointers left open on the files, etc. The only issue I could see is that if disk space was really tight you might want to expose the delete folder as a method to allow the option of that being called directly and then Dispose is just used to clean up after for all cases.
Note: in this example you probably want to call Directory.Delete(TempPath, true); because the method you're calling will throw an IOException if the folder isn't empty (something your catch will hide) - see https://msdn.microsoft.com/en-us/library/62t64db3%28v=vs.110%29.aspx
I have a very simple logging mechanism in my application which periodically writes a line to a file (a logging library would be overkill for my needs) which looks something like this:
private string logfile = #"C:\whatever.log";
public void WriteLine(string line)
{
using(FileStream fs = File.Open(logfile, FileMode.Append))
{
// Log Stuff
}
}
So any time I call that method, a new FileStream is created and disposed after logging is finished. So I considered using an already instantiated object to prevent the continuous creation of new objects:
private string logfile = #"C:\whatever.log";
private FileStream myStream = File.Open(logfile, FileMode.Append);
public void WriteLine(string line)
{
using(myStream)
{
// Log Stuff
}
}
However, the MSDN reference discourages this (last example), due to scope issues.
What does one do in that case? Is the overhead in my first example negligible?
The using statement doesn't do anything else than calling the Dispose() method of the object.
So considering your second example, after the first call to the WriteLine(string) method the filestream is disposed. So any other call, after the first one, to this Method will result in an exception.
Using the File.AppendText() method like Chris had suggested in the comment would be a way to go. But keep in mind, that using this or any other File... method will also open a stream and close and dispose it afterwards.
It will just result in less code.
The second approach does also dispose the stream every time you call WriteLine since you are also using the using-statement. MSDN discourages from this approach because the variable myStream does still "exist" even if the object is disposed. So that is more error-prone.
If you often need to use this method you should cosider to use the using "outside" or use a try-catch-finally:
var myLogger = new MyLogger();
try
{
// here is your app which calls myLogger.WriteLine(...) often
}
catch(Exception ex)
{
// log it
}
finally
{
myLogger.Dispose(); // myLogger is your Log class, dispose should call myStream.Dispose();
}
The overhead might not be negligible, but that might be beside the point.
When you are using using, the creation, acquisition of resource and the disposing of the used resources is nicely scoped. You know where it starts, where it's used, and where it's finished.
If you go for the second scenario, you know where it starts (it's when the containing class is created), but after that, you have no platform-guaranteed way to control where it's used, and where (if at all) the resources are disposed.
You can do this yourself if this is critical code, and your containing class implements the IDisposable pattern properly, but this can be tricky and not for the faint of heart :)
However, you stated in the question "a logging library would be overkill for my needs", so I think you are fine with the minimal overhead. IMHO, you should be fine with one of the ready-made File methods, like File.AppendAllText:
public void WriteLine(string line)
{
//add an enter to the end
line += Environment.NewLine;
File.AppendAllText(logfile, line);
}
or File.AppendAllLines:
public void WriteLine(string line)
{
File.AppendAllLines(logfile, new []{line});
}
I have an application that needs to redirect the output to Console.Write and Console.Writeline to somewhere else.
To elaborate further, my code starts a process at certain intervals. This proces is not written by me, or the company I work for, and I do not have source-code access.
I capture that output from that process because I need to know when I check up on the logs later if something has failed, and stuff like that, so I've redirected the output to a text-file like this:
String filename = "the-log-file-with-a-datetime-stamp.txt";
FileStream filestream = new FileStream(filename, FileMode.Create);
streamwriter = new StreamWriter(filestream);
streamwriter.AutoFlush = true;
Console.SetOut(streamwriter);
Console.SetError(streamwriter);
That works fine, sort of, but I would like to be able to redirect to more than one place, like I know redirect to a streamwriter.
Lets say for arguments sake I want it to redirect to the streamwriter AND write the line in a table in a database, and also show it in console, should someone have manually run the program.
How would I go about that?
Can I implement my own TextWriter and handle it there, and if so, how?
Please let me know if I can clarify further.
The simplest way would be to do as you suggested and write your own TextWriter-derived class. You could then use it to write to multiple other TextWriter instances.
Documentation for TextWriter says, in its "Notes to inheritors":
A derived class must minimally implement the TextWriter.Write(Char) method to make a useful instance of TextWriter.
So your derived TextWriter class would look something like:
public class MultiTextWriter: TextWriter
{
private List<TextWriter> _writers = new List<TextWriter>();
public void AddWriter(TextWriter writer)
{
_writers.Add(writer);
}
public override void Write(char ch)
{
foreach (var writer in _writers)
{
try
{
writer.Write(ch);
}
catch (ObjectDisposedException)
{
// handle exception here
}
catch (IOException)
{
// handle exception here
}
}
}
}
And to use it...
MultiTextWriter Writer = new MultiTextWriter();
StreamWriter sw1 = new StreamWriter(...);
StreamWriter sw2 = new StreamWriter(...);
Writer.AddWriter(sw1);
Writer.AddWriter(sw2);
Console.SetOut(Writer);
Console.SetError(Writer);
Note that my class and examples are pretty minimal. In particular, you'll need to add code that closes the individual streams. And you'll have to decide how you want to handle write errors.
You can override other TextWriter write methods if you want to potentially get better performance, but it's quite possible that just overriding the Write(char) method will perform well enough. It will depend on how much data is going out and how many different destinations.
Redirect the output to a MemoryStream, and monitor it (cycle+sleep). Upon arrival of data, send it to wherever you need.
You can create a CompositeStream class derived from the Stream class which will support only writing. And in overridden Write method you can write to any number of underlying streams.
Example of solution: Write your own class that derives from TextWriter which will echo the output to a StreamWriter and your other place.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I would like to implement logging in my application, but would rather not use any outside frameworks like log4net.
So I would like to do something like DOS's echo to a file. What is the most effective way to do it?
Is there a way to log unhandled exceptions logged without using an outside framework?
public void Logger(string lines)
{
//Write the string to a file.append mode is enabled so that the log
//lines get appended to test.txt than wiping content and writing the log
using(System.IO.StreamWriter file = new System.IO.StreamWriter("c:\\test.txt", true))
{
file.WriteLine(lines);
}
}
For more information MSDN
I would rather not use any outside
frameworks like log4j.net.
Why? Log4net would probably address most of your requirements.
For example check this class: RollingFileAppender.
Log4net is well documented and there are thousand of resources and use cases on the web.
You can write directly to an event log. Check the following links:
http://support.microsoft.com/kb/307024
http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog.aspx
And here's the sample from MSDN:
using System;
using System.Diagnostics;
using System.Threading;
class MySample{
public static void Main(){
// Create the source, if it does not already exist.
if(!EventLog.SourceExists("MySource"))
{
//An event log source should not be created and immediately used.
//There is a latency time to enable the source, it should be created
//prior to executing the application that uses the source.
//Execute this sample a second time to use the new source.
EventLog.CreateEventSource("MySource", "MyNewLog");
Console.WriteLine("CreatedEventSource");
Console.WriteLine("Exiting, execute the application a second time to use the source.");
// The source is created. Exit the application to allow it to be registered.
return;
}
// Create an EventLog instance and assign its source.
EventLog myLog = new EventLog();
myLog.Source = "MySource";
// Write an informational entry to the event log.
myLog.WriteEntry("Writing to event log.");
}
}
If you are looking for a real simple way to log, you can use this one liner. If the file doesn't exist, it's created.
System.IO.File.AppendAllText(#"c:\log.txt", "mymsg\n");
I used to write my own error logging until I discovered ELMAH. I've never been able to get the emailing part down quite as perfectly as ELMAH does.
If you want to stay close to .NET check out Enterprise Library Logging Application Block. Look here. Or for a quickstart tutorial check this. I have used the Validation application Block from the Enterprise Library and it really suits my needs and is very easy to "inherit" (install it and refrence it!) in your project.
If you want your own custom Error Logging you can easily write your own code. I'll give you a snippet from one of my projects.
public void SaveLogFile(object method, Exception exception)
{
string location = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\FolderName\";
try
{
//Opens a new file stream which allows asynchronous reading and writing
using (StreamWriter sw = new StreamWriter(new FileStream(location + #"log.txt", FileMode.Append, FileAccess.Write, FileShare.ReadWrite)))
{
//Writes the method name with the exception and writes the exception underneath
sw.WriteLine(String.Format("{0} ({1}) - Method: {2}", DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString(), method.ToString()));
sw.WriteLine(exception.ToString()); sw.WriteLine("");
}
}
catch (IOException)
{
if (!File.Exists(location + #"log.txt"))
{
File.Create(location + #"log.txt");
}
}
}
Then to actually write to the error log just write (q being the caught exception)
SaveLogFile(MethodBase.GetCurrentMethod(), `q`);