I have an if/else statement that is not working.
while (rdr.Read())
{
string permission = rdr["Permission"].ToString();
if (permission == "Exec")
{
Run my code
}
else
{
lblErrorStart.Visible = true;
}
}
If Permission does equal Exec then everything works fine but (when stepping through the code) I have noticed that when Permission does not equal Exec, it does not trigger the Else. It just goes back to the while statement and stops. Let me know if I need to provide any more code.
Note: I only have Exec in the database. Everything else is null.
I have noticed that when Permission does not equal Exec, it does not trigger the Else.
I have a very hard time believing that. Please show us the exact contents of permission when it does not equal "Exec".
Also realize that setting the label to visible will not update as soon as that code is executed. This is because you are not allowing the Windows Message Loop to process messages. So even though the Visible property is set to true, a WM_PAINT message is never processed (until your loop exits), so the appearance of your control will not change.
EDIT:
As Brian Gideon points out in a comment, your executable version may be out of sync with your code. Rebuild the entire project and try it again.
Sometimes when testing exact equality, you fail based on what you do NOT see... If your data is from a record set, or other structure and the actual value is NOT trimmed(), it will fail...
"Exec " == "Exec" will fail
Try
string permission = rdr["Permission"].ToString().Trim();
Basically it's an if else statement like stated:
if(label1.Text == "True")
{
label1.Forecolor = Color.Green;
}
else
{
label1.Text = "ERROR!";
label1.Forecolor = Color.Red;
}
Also, you can do multiple if statements and if none of them are relatively true you can have them all lead to the else statement.
Related
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.
}
}
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 am working on an app that uses location services. If I am debugging, the app works fine. If I start without debugging, on the first run (after rebuild), it crashes when asking for authorization to use location services. What happens is that if you let it sit, with the messagebox showing long enough (5-10 seconds), it crashes. If I start without debugging again, it works fine (though it doesn't show the messagebox again, because somehow it gets past that line to the next line AFTER the conditional statement, where it sets first run false (I assume, because it doesn't show again).
Again, if I am debugging, no problems. If I start without debugging, it dies. This is the case when building in either the Debug or Release modes.
If I comment this block of code out, it executes without a problem. If I click OK quickly, it executes without a problem.
if (settings.FirstRunLocationPermission)
{
string message = "Do you wish to use location services to see your location on the map? Your location is not being tracked. You can change this authorization in the settings.";
//if (MessageBox.Show(message,"authorization",MessageBoxButton.OKCancel) == MessageBoxResult.OK)
//{
// settings.AllowLocation = true;
//}
settings.FirstRunLocationPermission = false;
}
I would greatly appreciate it if anyone can explain to me why a simple messagebox checking for ok would cause a problem like this. Thanks!
Most likely you are showing the MessageBox in OnNavigatedTo. If that is the case, this SO answer should help. The problem is that if the user does not press a button your app will crash since the framework thinks that navigation has failed.
And yes, this behaviour occurs to me only when debugger is not attached.
If you look at the MSDN Documentation for the method, the reasons for the possible Exceptions is fairly clear:
MDSN - MessageBox.Show Method
The other possibility is that there is some code running in the setter for the settings.AllowLocation property that is throwing the Exception. It would help if you included the actual Exception being thrown.
I use it this way, and it works :
var msg = MessageBox.Show("Do you .... ?", "Title", MessageBoxButton.OKCancel);
if(msg == MessageBoxResult.OK)
{
//Do something;
}
Good luck
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 the following code in a C# windows form application.
if (myGrid.Rows.Count != 0)
{
// do something
}
else
{
MessageBox.Show("Test");
}
The message box shows up in Debug mode but not in release mode. Any idea why?
I am having similar issues with other code as well
For instance
if (!myParameter)
this.mycheckBox.Enabled = false;
else
this.mycheckBox.Enabled = true;
The above code works in debug mode not in release. Not sure why.
Thanks
In release mode myGrid.Rows.Count != 0 must be true, try putting another MessageBox.Show there.
Probably because your if statement is true in release mode.
Remove the if and keep the MessageBox.Show("Test"); and that should work just fine
EDIT
You can even go a step further by putting a breakpoint at the if statement and seeing what value is being returned. This would work for both sections of code.
Try putting messageboxes or breakpoints before all your if statements. What is the value of the parameter you are about to test?
If this does not shed any light, make a new, empty winForms project, and put in a messagebox with no conditions. If that works, start adding your old code to it piece by piece and watch to see where it breaks.