I am examining some code examples and have seen similar variation to the following examples, one of them made me very curious.
When a goto_tag is placed before a try statement. This makes complete sense and it just runs through the try again.
retry_tag: //the goto tag to re-attempt to copy a file
try {
fileInfo.CopyTo( toAbsolutePath + fileInfo.Name, true ); //THIS LINE MIGHT FAIL IF BUSY
} catch {
Thread.Sleep(500); //wait a little time for file to become available.
goto retry_tag; //go back and re-attempt to copy
}
However, as the following was presented to me I did not understand it. When a goto_tag is placed within the try statement, and is called from within the catch block.
try {
retry_tag: //the goto tag to re-attempt to copy a file
fileInfo.CopyTo( toAbsolutePath + fileInfo.Name, true ); //THIS LINE MIGHT FAIL IF BUSY
} catch {
Thread.Sleep(500); //wait a little time for file to become available.
goto retry_tag; //go back and re-attempt to copy
}
Is the try block resurrected? Or are the two examples functionally identical, or is this an completely illegal operation and won't even compile?
This is all purely out of curiosity, and of course I would prefer the first example, if either of them..
Thanks for any insight!!
To actually answer your question:
No, these are not the same.
The first example will compile; the second is illegal.
(The matter of whether you should write code like this is a different question... and off course, you should not if you can help it.)
You can implement a simple while instead of goto:
// loop until ...
while (true) {
try {
fileInfo.CopyTo(Path.Combine(toAbsolutePath, fileInfo.Name), true);
// ... file copied
break;
}
catch (IOException) {
Thread.Sleep(500); //wait a little time for file to become available.
}
}
Related
Argh! I'm back, guys! I hate having to bother others with my issues, but I've been working on this for like 3 days now.
Using the Chat Application example, I molded it into my game. The client and server connect appropriately but... My client is having some trouble. :/
public static void appendText(RichTextBox box, string line)
{
if (box == null || box.IsDisposed)
return;
//try
//{
box.AppendText(line + Environment.NewLine);
ScrollRichTextBox(box);
//}
//catch
//{
// Program.debug.print("Something went wrong.");
//}
}
The AppendText line keeps throwing an exception (InvalidOperationException). I commented out the try-catch, hoping the compiler would give me more advice on what's wrong and maybe how to fix it, but I get no where with its help.
In the examples, I can run that code without getting this error. I don't know where I went wrong here.
Oh, AppendText is called by...
public static void GotMessage(object peer)
{
NetIncomingMessage im;
while ((im = s_client.ReadMessage()) != null)
{
// handle incoming message
switch (im.MessageType)
{
case NetIncomingMessageType.DebugMessage:
case NetIncomingMessageType.ErrorMessage:
case NetIncomingMessageType.WarningMessage:
case NetIncomingMessageType.VerboseDebugMessage:
string text = im.ReadString();
//TextControl.appendText(menuWindow.richTextBoxStatus, text);
Program.printStatus(text);
break;
case NetIncomingMessageType.StatusChanged:
NetConnectionStatus status = (NetConnectionStatus)im.ReadByte();
/*if (status == NetConnectionStatus.Connected)
s_form.EnableInput();
else
s_form.DisableInput();
*/
//if (status == NetConnectionStatus.Disconnected)
//s_form.button2.Text = "Connect";
string reason = im.ReadString();
Program.printStatus(status.ToString() + ": " + reason);
break;
case NetIncomingMessageType.Data:
// incoming packet from the server, handle data
int size = im.ReadInt32();
byte[] bData = im.ReadBytes(size);
string data = Encoding.Unicode.GetString(bData);
Program.debug.print(data);
Program.printToChat(data);
handleData(data);
break;
default:
Program.printStatus("Unhandled type: " + im.MessageType + " " + im.LengthBytes + " bytes");
break;
}
}
}
where printToChat or printStatus are found. Those methods contain the calls to AppendText.
I tried to post to the Lidgren Google Group when the error first popped up, but I haven't gotten a response back from them, so I'm hoping people here could have the information I seek. :)
I can provide more information and code if needed (as always, heh).
(I did Google how to make thread-safe calls to UI elements, but the code was just too confusing to comprehend. When I finally thought I implemented a solution, it just refused to work at all..)
Pfft, look at me, figuring things out.
I was able to successfully add delegate methods to my forms so that they can be access across threads. Or so I'm led to believe. The code now functions as intended.
I coooould add code, to show what I did. And I will if anyone needs help with this type of problem. I think I'm capable of explaining it, but MSDN works wonders.
As always, I just had to ask the question, and read comments to be led in the right direction.
I really need to stop asking questions I end up answering days later. :/
I'm sooo sorry. I feel really bad for taking up space and wasting time.
edit: I've also written a very clever way of circumventing needing to use delegates. However, it requires the use of a timer, or a loop that also repaints the windows form every now and then (I've used a timer).
While looking at the source code of System.ServiceModel.Channels.BufferManager, I noticed this method:
void TuneQuotas()
{
if (areQuotasBeingTuned)
return;
bool lockHeld = false;
try
{
try { }
finally
{
lockHeld = Monitor.TryEnter(tuningLock);
}
// Don't bother if another thread already has the lock
if (!lockHeld || areQuotasBeingTuned)
return;
areQuotasBeingTuned = true;
}
finally
{
if (lockHeld)
{
Monitor.Exit(tuningLock);
}
}
//
// DO WORK... (code removed for brevity)
//
areQuotasBeingTuned = false;
}
Obviously, they want only one thread to run TuneQuotas(), and other threads to not wait if it is already being run by another thread. I should note that the code removed was not try protected.
I'm trying to understand the advantages of this method above over just doing this:
void TuneQuotas()
{
if(!Monitor.TryEnter(tuningLock)) return;
//
// DO WORK...
//
Monitor.Exit(tuningLock);
}
Any ideas why they might have bothered with all that? I suspect the way they use the finally blocks is to guard against a thread abort scenario, but I still don't see the point because, even with all this code, TuneQuotas() would be locked for good if that one thread doesn't make it all the way to the end to set areQuotasBeingTunes=false, for one reason or another. So is there something cool about this pattern that I'm missing?
EDIT:
As a side note, it seems the method exists in .NET 4.0, which I confirmed using this code running on framework 4 (although I cannot confirm that the content of the method hasn't changed from what I found on the web):
var buffMgr = BufferManager.CreateBufferManager(1, 1);
var pooledBuffMgrType = buffMgr.GetType()
.GetProperty("InternalBufferManager")
.GetValue(buffMgr, null)
.GetType();
Debug.WriteLine(pooledBuffMgrType.Module.FullyQualifiedName);
foreach (var methodInfo in pooledBuffMgrType
.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic))
{
Debug.WriteLine(methodInfo.Name);
}
which outputs:
C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Runtime.DurableInstancing\v4.0_4.0.0.0__3 1bf3856ad364e35\System.Runtime.DurableInstancing.dll
ChangeQuota
DecreaseQuota
FindMostExcessivePool
FindMostStarvedPool
FindPool
IncreaseQuota
TuneQuotas
Finalize
MemberwiseClone
I'll add some comments:
void TuneQuotas()
{
if (areQuotasBeingTuned)
return; //fast-path, does not require locking
bool lockHeld = false;
try
{
try { }
finally
{
//finally-blocks cannot be aborted by Thread.Abort
//The thread could be aborted after getting the lock and before setting lockHeld
lockHeld = Monitor.TryEnter(tuningLock);
}
// Don't bother if another thread already has the lock
if (!lockHeld || areQuotasBeingTuned)
return; //areQuotasBeingTuned could have switched to true in the mean-time
areQuotasBeingTuned = true; //prevent others from needlessly trying to lock (trigger fast-path)
}
finally //ensure the lock being released
{
if (lockHeld)
{
Monitor.Exit(tuningLock);
}
}
//
// DO WORK... (code removed for brevity)
//
//this might be a bug. There should be a call to Thread.MemoryBarrier,
//or areQuotasBeingTuned should be volatile
//if not, the write might never reach other processor cores
//maybe this doesn't matter for x86
areQuotasBeingTuned = false;
}
The simple version you gave does not protect against some problems. At the very least it is not exception-safe (lock won't be released). Interestingly, the "sophisticated" version, doesn't either.
This method has been removed from .NET 4.
Until .NET 4.0 there was essentially a bug in the code that was generated by a lock statment. It would generate something similar to the following:
Monitor.Enter(lockObject)
// see next paragraph
try
{
// code that was in the lock block
}
finally
{
Monitor.Exit(lockObject);
}
This means that if an exception occurred between Enter and try, the Exit would never be called. As usr alluded to, this could happen due to Thread.Abort.
Your example:
if(!Monitor.TryEnter(tuningLock)) return;
//
// DO WORK...
//
Monitor.Exit(tuningLock);
Suffers from this problem and more. The window in which this code and become interrupted and Exit not be called is basically the whole block of code--by any exception (not just one from Thread.Abort).
I have no idea why most code was written in .NET. But, I surmise that this code was written to avoid the problem of an exception between Enter and try. Let's look at some of the details:
try{}
finally
{
lockHeld = Monitor.TryEnter(tuningLock);
}
Finally blocks basically generate a constrained execution region in IL. Constrained execution regions cannot be interrupted by anything. So, putting the TryEnter in the finally block above ensures that lockHeld reliably holds the state of the lock.
That block of code is contained in a try/finally block whose finally statement calls Monitor.Exit if tuningLock is true. This means that there is no point between the Enter and the try block that can be interrupted.
FWIW, this method was still in .NET 3.5 and is visible in the WCF 3.5 source code (not the .NET source code). I don't know yet what's in 4.0; but I would imagine it would be the same; there's no reason to change working code even if the impetus for part of its structure no longer exists.
For more details on what lock used to generate see http://blogs.msdn.com/b/ericlippert/archive/2007/08/17/subtleties-of-c-il-codegen.aspx
Any ideas why they might have bothered with all that?
After running some tests, I think see one reason (if not THE reason): They probably bothered with all that because it is MUCH faster!
It turns out Monitor.TryEnter is an expensive call IF the object is already locked (if it's not locked, TryEnter is still very fast -- no problems there). So all threads, except the first one, are going to experience the slowness.
I didn't think this would matter that much; since afterall, each thread is going to try taking the lock just once and then move on (not like they'd be sitting there, trying in a loop). However, I wrote some code for comparison and it showed that the cost of TryEnter (when already locked) is significant. In fact, on my system each call took about 0.3 ms without the debugger attached, which is several orders of magnitude slower than using a simple boolean check.
So I suspect, this probably showed up in Microsoft's test results, so they optimized the code as above, by adding the fast track boolean check. But that's just my guess..
I have a method that stops a service(s) but I also need to delete the logs. Usually this is not a problem but the process can take a little bit of time before closing. Again, although the service appears stopped, the process does take additional time to close properly. Since the process is still running, I cannot delete the logs so I need to find a way to monitor the .exe to know when its safe to delete the logs.
so far my best option is a do while loop, unfortunately the first iteration of the delete statement throws an exception and stops the program.
do
{
// delete logs
}
while (System.Diagnostics.Process.GetProcessesByName(processName, machineName).Length > 0);
Im sure there is a simple solution but my lack of experience is the real problem.
This is probably not the best answer either, but you could invert the loop to:
while (System.Diagnostics.Process.GetProcessesByName(processName, machineName).Length > 0)
{
// delete log files.
}
I would suppose this would evalutate the condition of the loop before executing the contents. But according to your statements, this will not execute the code until the process has exited.
A hackish way around this is to perform a loop, and break out manually once the conditions:
bool CloseProcessOperation = true; // Control variable incase you want to abort the loop
while (CloseProcessOperation)
{
if (System.Diagnostics.Process.GetProcessesByName(processName, machineName).Length > 0) { break; }
// break if no logs exist
// break for some other condition
// etc
// delete logs
}
I have a foreach loop that starts a process within a try/catch. In the finally section of my try/catch/finally I am trying to ensure the the process does not have a handle on any files. I have to delete files that were being processed.
Nothing I have tried seems to be working. I continue to get System.IO exceptions. "The file is currently in use by another process."
You can see in the finally I am using the WaitForExit() before returning from this method. The very next method call is one to delete files. Why would the process still be open or have a handle on any of these file after this?
Thanks!
try
{
foreach (var fileInfo in jsFiles)
{
//removed for clarity
_process.StartInfo.FileName = "\"C:\\Program Files\\Java\\jre6\\bin\\java\"";
_process.StartInfo.Arguments = stringBuilder.ToString();
_process.StartInfo.UseShellExecute = false;
_process.StartInfo.RedirectStandardOutput = true;
_process.Start();
}
}
catch (Exception e)
{
BuildMessageEventArgs args = new BuildMessageEventArgs("Compression Error: " + e.Message,
string.Empty, "JSMin", MessageImportance.High);
BuildEngine.LogMessageEvent(args);
}
finally
{
_process.WaitForExit();
_process.Close();
}
There's something seriously wrong here. You're starting a bunch of processes, but only waiting for the last spawned one to exit.
Are you sure you don't want the foreach outside the try block?
If you tell us more about what exactly you're trying to do, we could provide better suggestions.
I think you need to restructure your code. As it stands a failure for any of the processes in the foreach will cause an exit from the loop. Even if everything does succeed then your WaitForExit and Close calls in the finally block will only address the last process from the loop above.
You need to deal with each process and its success and/or failure individually. Create a method that accepts a fileInfo parameter and spawns and waits on each process. Move your loop into the client code that will be calling the suggested method.
Is the process a Console application or a GUI application?
For a GUI application, you will have to do Process.CloseMainWindow.
foreach (var fileInfo in jsFiles)
{
using (Process process = new Process())
{
try
{
//Other stuff
process.Start();
}
catch (...)
{
//Exception Handling goes here...
}
finally
{
try
{
process.WaitForExit();
}
catch (...)
{
}
}
}
}
Process.WaitForExit() might throw an exception, so it needs a try/catch of it's own.
If you create the process in the using statement, you don't have to worry about closing it, .NET will dispose of it properly.
It's usually better to not precede local variables with an underscore character. Most people just use that for their fields.
My program is unable to File.Move or File.Delete a file because it is being used "by another process", but it's actually my own program that is using it.
I use Directory.GetFiles to initially get the file paths, and from there, I process the files by simply looking at their names and processing information that way. Consequently all I'm doing is working with the strings themselves, right? Afterwards, I try to move the files to a "Handled" directory. Nearly all of them will usually move, but from time to time, they simply won't because they're being used by my program.
Why is it that most of them move but one or two stick around? Is there anything I can do to try freeing up the file? There's no streams to close.
Edit Here's some code:
public object[] UnzipFiles(string[] zipFiles)
{
ArrayList al = new ArrayList(); //not sure of proper array size, so using arraylist
string[] files = null;
for (int a = 0; a < zipFiles.Length; a++)
{
string destination = settings.GetTorrentSaveFolder() + #"\[CSL]--Temp\" + Path.GetFileNameWithoutExtension(zipFiles[a]) + #"\";
try
{
fz.ExtractZip(zipFiles[a], destination, ".torrent");
files = Directory.GetFiles(destination,
"*.torrent", SearchOption.AllDirectories);
for (int b = 0; b < files.Length; b++)
al.Add(files[b]);
}
catch(Exception e)
{}
}
try
{
return al.ToArray(); //return all files of all zips
}
catch (Exception e)
{
return null;
}
}
This is called from:
try
{
object[] rawFiles = directory.UnzipFiles(zipFiles);
string[] files = Array.ConvertAll<object, string>(rawFiles, Convert.ToString);
if (files != null)
{
torrents = builder.Build(files);
xml.AddTorrents(torrents);
directory.MoveProcessedFiles(xml);
directory.MoveProcessedZipFiles();
}
}
catch (Exception e)
{ }
Therefore, the builder builds objects of class Torrent. Then I add the objects of class Torrent into a xml file, which stores information about it, and then I try to move the processed files which uses the xml file as reference about where each file is.
Despite it all working fine for most of the files, I'll get an IOException thrown about it being used by another process eventually here:
public void MoveProcessedZipFiles()
{
string[] zipFiles = Directory.GetFiles(settings.GetTorrentSaveFolder(), "*.zip", SearchOption.TopDirectoryOnly);
if (!Directory.Exists(settings.GetTorrentSaveFolder() + #"\[CSL] -- Processed Zips"))
Directory.CreateDirectory(settings.GetTorrentSaveFolder() + #"\[CSL] -- Processed Zips");
for (int a = 0; a < zipFiles.Length; a++)
{
try
{
File.Move(zipFiles[a], settings.GetTorrentSaveFolder() + #"\[CSL] -- Processed Zips\" + zipFiles[a].Substring(zipFiles[a].LastIndexOf('\\') + 1));
}
catch (Exception e)
{
}
}
}
Based on your comments, this really smells like a handle leak. Then, looking at your code, the fz.ExtractZip(...) looks like the best candidate to be using file handles, and hence be leaking them.
Is the type of fz part of your code, or a third party library? If it's within your code, make sure it closes all its handles (the safest way is via using or try-finally blocks). If it's part of a third party library, check the documentation and see if it requires any kind of cleanup. It's quite possible that it implements IDisposable; in such case put its usage within a using block or ensure it's properly disposed.
The line catch(Exception e) {} is horribly bad practice. You should only get rid of exceptions this way when you know exactly what exception may be thrown and why do you want to ignore it. If an exception your program can't handle happens, it's better for it to crash with a descriptive error message and valuable debug information (eg: exception type, stack trace, etc), than to ignore the issue and continue as if nothing had gone wrong, because an exception means that something has definitely gone wrong.
Long story short, the quickest approach to debug your program would be to:
replace your generic catchers with finally blocks
add/move any relevant cleanup code to the finally blocks
pay attention to any exception you get: where was it thrown form? what kind of exception is it? what the documentation or code comments say about the method throwing it? and so on.
Either
4.1. If the type of fz is part of your code, look for leaks there.
4.2. If it's part of a third party library, review the documentation (and consider getting support from the author).
Hope this helps
What this mean: "there is no streams to close"? You mean that you do not use streams or that you close them?
I believe that you nevertheless have some opened stream.
Do you have some static classes that uses this files?
1. Try to write simple application that will only parse move and delete the files, see if this will works.
2. Write here some pieces of code that works with your files.
3. Try to use unlocker to be sure twice that you have not any other thing that uses those files: http://www.emptyloop.com/unlocker/ (don't forget check files for viruses :))
Class Path was handling multiple files to get me their filenames. Despite being unsuccessful in reproducing the same issue, forcing a garbage collect using GC.Collect at the end of the "processing" phase of my program has been successful in fixing the issue.
Thanks again all who helped. I learned a lot.