The following code was a proof of concept for a message batching routine. Do I avoid goto like the plague and rewrite this code? Or do you think the goto is an expressive way to get this done?
If you'd rewrite please post some code...
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
HaveAnotherMessage:
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
if (queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
{
goto HaveAnotherMessage;
}
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
// queue processing code
}
Pretty much sums up my thoughts on "goto."
Goto is bad programming practice for many reasons. Chief among them is that there is almost never a reason for it. Someone posted a do..while loop, use that. Use a boolean to check if you should continue. Use a while loop. Goto's are for interpreted languages and a call back to assembler days (JMP anyone?). You're using a high level language for a reason. So that you and everyone else doesn't look at your code and get lost.
To keep this answer somewhat current I'd like to point out that a combination of goto and bracing errors caused a major SSL bug in iOS and OS X.
Replace the goto with a do-while, or simply a while loop if you don't want the "always run once" functionality you have right now.
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
do {
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
} while(queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
// queue processing code
}
It's so amazingly easy to rid yourself of GOTO in this situation it makes me cry:
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
bool hasAnotherMessage = true
while(hasAnotherMessage)
{
hasAnotherMessage = false;
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
if (queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
{
hasAnotherMessage = true;
}
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
}
// queue processing code
}
I guess the goto is SLIGHTLY more readable intuitively... But if you WANTED to avoid it I think all you'd have to do is throw the code in a while(true) loop, and then have a break statement at the end of the loop for a normal iteration. And the goto could be replaced with a continue statement.
Eventually you just learn to read and write loops and other control flow structures instead of using goto statements, at least in my experience.
Kind of related to Josh K post but I'm writing it here since comments doesn't allow code.
I can think of a good reason: While traversing some n-dimensional construct to find something. Example for n=3 //...
for (int i = 0; i < X; i++)
for (int j = 0; j < Y; j++)
for (int k = 0; k < Z; k++)
if ( array[i][j][k] == someValue )
{
//DO STUFF
goto ENDFOR; //Already found my value, let's get out
}
ENDFOR: ;
//MORE CODE HERE...
I know you can use "n" whiles and booleans to see if you should continue.. or you can create a function that maps that n-dimensional array to just one dimension and just use one while but i believe that the nested for its far more readable.
By the way I'm not saying we should all use gotos but in this specific situation i would do it the way i just mentioned.
You could refactor is to something like this.
while (queue.Count < this.batch && buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
buffer = null;
if (item != null)
{
queue.Enqueue(item);
socket.Recv(out buffer, ZMQ.NOBLOCK)
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
Umm, I'm not really sure you want to goto out of a try block. I'm pretty sure that is not a safe thing to do, though I'm not 100% sure on that. That just doesn't look very safe...
Wrap the "HaveAnotherMessage" into a method that takes in the buffer and may call itself recursively. That would seem to be the easiest way to fix this.
I would avoid goto in this case, and refactor it. The method reads too long in my opinion.
I think your method is too big. It mixes different levels of abstraction, like error processing, message retrieval and message processing.
If you refactor it in different methods, the goto naturally goes away (note: I assume your main method is called Process):
...
private byte[] buffer;
private Queue<TraceItem> queue;
public void Process() {
queue = new Queue<TraceItem>(batch);
while (connected) {
ReceiveMessage();
TryProcessMessage();
}
}
private void ReceiveMessage() {
try {
socket.Recv(out buffer);
}
catch {
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the processing
}
}
private void TryProcessMessage() {
try {
ProcessMessage();
}
catch (Exception ex) {
ProcessError(ex);
}
}
private void ProcessMessage() {
if (buffer == null) return;
var item = TraceItemSerializer.FromBytes(buffer);
if (item == null) return;
queue.Enqueue(item);
if (HasMoreData()) {
TryProcessMessage();
}
}
private bool HasMoreData() {
return queue.Count < batch && socket.Recv(out buffer, ZMQ.NOBLOCK);
}
private void ProcessError(Exception ex) {
ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
tracer.TraceException(TraceEventType.Error, 0, ex);
}
...
Related
Im looking for a simple way, to repeat a method, when an element(selector) for example a button on a webpage cant be found.
My idea or my plan is, that:
If the selector can be found, the method is done
If the selector cant be found, it should repeat the "FindElement" method up to maximal 3 times
If the selector cant be found after the third try, it should give me an output message of the "NoSuchElementException e"
I tried different loops and i always end up having endless loops like in the code below.
public static void FindElement(IWebDriver webDriver, string selector)
{
int maxTries = 0;
try
{
webDriver.FindElement(By.XPath(selector));
Console.WriteLine("Element found.");
}
catch (NoSuchElementException e)
{
if (maxTries !> 3 )
{
Console.WriteLine("Element, not found. Retrying.");
maxTries++;
FindElement(webDriver, selector);
}
else
{
Console.WriteLine(e);
}
}
}
What a coincidence: Just a few days ago I wrote a short helper method to separate "retry logic" from "business logic".
private T Retry<T>(Func<T> action, int maxRetryCount, int waitMilliseconds,
Func<Exception, bool> retryCondition)
{
var retryCount = 0;
while (true)
{
try
{
// If the action was successful (no exception thrown),
// we can leave the method.
return action();
}
catch (Exception ex) when (retryCount < maxRetryCount && retryCondition(ex))
{
retryCount += 1;
Thread.Sleep(waitMilliseconds);
}
}
}
Which would be called as follows in your case:
var element = Retry(() => webDriver.FindElement(By.XPath(selector)),
2, 0,
ex => ex is NoSuchElementException);
Whenever the maximum number of retries is reached, the exception is not caught any more (the when condition fails) and can be caught by your regular exception handling logic instead.
Since you are trying to automate a web browser, you might consider passing something else than 0 as waitMilliseconds, to give the browser time to render the elements that are still missing.
Why don't you put the maxTry outside of your function?
int maxTry=3;
string errorMessage="";
for(int i=0;i<maxTry;i++)
{
try
{
FindElement(webDriver,selector)
errorMessage="";
break;
}
catch (NoSuchElementException e)
{
errorMessage=e;
}
}
if(errorMessage!="")
{
Console.WriteLine(e);
}
else
{
Console.WriteLine("Element found.");
}
For recursion, you should pass the amount of remaining iterations to the function, and decrement it for each iteration.
public static void FindElement(IWebDriver webDriver, string selector, int iterations = 3)
{
iterations--;
if (iterations < 0)
{
Console.WriteLine("Max iterations passed, exiting")
return;
}
try
{
webDriver.FindElement(By.XPath(selector));
Console.WriteLine("Element found.");
}
catch (NoSuchElementException e)
{
Console.WriteLine("Element not found. Retrying.");
FindElement(webDriver, selector, iterations);
}
}
I am trying to use lock for read and write to list at the same time. I adding bytes from serial port to a list while processing these bytes by reading from same list with the help of lock. My problem is that while running it in debug mode it is working fine but while running normally it showing exception. Following is my code.
private void receiveData(object sender, SerialDataReceivedEventArgs e)
{
while (connectComPort.BytesToRead > 0)
receivedBytes1.Add((byte)connectComPort.ReadByte());
}
int tint = 0;
private static readonly object _object = new object();
private void modprocessReceivedBuffer()
{
while (1 == 1)
{
try
{
if (receivedBytes1.Count() > tint)
{
List<byte> receivedBytes12 = null;
lock (_object)
{
receivedBytes12 = receivedBytes1.GetRange(tint, 2).ToList<byte>(); //LINE 1
}
if (receivedBytes12[0] == 0x0D)
{
if (receivedBytes12[1] == 0xAF)
{
try
{
var tiff = receivedBytes1.GetRange(tint, ((int)receivedBytes1[tint + 4])).ToList<byte>();
tint += (int)receivedBytes1[tint + 4];
modifiedProcess(tiff);
if (receivedBytes1.Count() == tint)
{
receivedBytes1.Clear();
tint = 0;
Thread.Sleep(20);
}
}
catch
{
}
}
}
else
{
tint += 1;
}
}
}
catch (Exception ex)
{
Log.Error("bug : " + ex.ToString());
}
}
}
Line 1 shows "System.ArgumentException: Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection" while running the code normally. I am not able to catch this error while running in debug mode. My second question is that if their is any thread safe list like structure in c#?
I would also like to add that I am receiving data from port at a very fast rate 16000 bytes/sec average.
I have several variations of the following code within methods that are being used for Selenium testing (waits for certain events before returning) and I would like to refactor it and make it reusable so I have the logic controlling the delay & try/catch as a generic method but be able to swap in and out conditions depending on situation.
Is there an easy way to achieve this?
Code:
for (int second = 0; second <= 10; second++)
{
try
{
// bit that needs to vary
matchedAddresses = driver.FindElements(By.ClassName("addresslookup"));
if (matchedAddresses.Count > 0)
{
break;
}
}
catch (Exception)
{
}
Thread.Sleep(1000);
}
return matchedAddresses.Count;
You want function that takes argument of something like Func<int> - method that returns number of elements (or enumerable Func<IEnumerable<sometype>>)
public int GetCountOfElementsWithWait(Func<int> test)
{
.....
var count = test();
....
}
Seems a bit too obvious, but would this work?
public int GetCountOfElementsByClassName(string className)
{
for (int second = 0; second <= 10; second++)
{
try
{
// bit that needs to vary
matchedElements = driver.FindElements(By.ClassName(className));
if (matchedElements.Count > 0)
{
break;
}
}
catch (Exception)
{
}
Thread.Sleep(1000);
}
return matchedElements.Count;
}
I want to check that a variable (e.g "totalSum" is bigger than 0) with try catch, and if it isn't
I want the program to cancel and write out a message to the user.
Following code is by obvious reasons not possible to compile, but hopefully you see what I want with it:
while (true)
{
try
{
totalSum > 0;
break;
}
catch
{
Console.WriteLine("Total sum is too small.");
End program
}
}
Is it possible to do this with try...catch and if so, how to do it?
A try/catch block can do this:
try
{
if (totalSum < 0)
throw new ApplicationException();
}
catch (Exception ex)
{
Console.WriteLine("Total sum is too small");
Environment.Exit(1);
}
But a simple if statement can do this with a lot less work:
if (totalSum < 0)
{
Console.WriteLine("Total sum is too small");
Environment.Exit(1);
}
You could do this, though I don't recommend it:
try
{
if (totalSum < 0)
throw new ArgumentOutOfRangeException("totalSum", "Total sum is too small.");
}
catch (ArgumentOutOfRangeException ex)
{
Console.WriteLine(ex.Message);
}
you can throw an exception
if (totalSum < 0)
{
throw new InvalidArgumentException("totalSum");
}
There is not much reason to use try catch.
You can do
try {
if(!(totalSum > 0)) throw new Exception();
} catch {
Console.WriteLine("Total sum is too small.");
}
But really, no reason to do so - why do you have to use try..catch?
There is no reason to use a try/catch block here. Use exceptions for exceptional circumstances only. In your case, just use if and else:
if (totalSum > 0)
{
// Good! Do something here
}
else
{
// Bad! Tell the user
Console.WriteLine("Bad user!");
}
Or, if you'd like to loop:
int totalSum = 0;
while (totalSum <= 0)
{
totalSum = GetSum();
if (totalSum <= 0)
Console.WriteLine("Too small!");
}
I have a function that calls a test on each object. I want to be able to retest if the current test fails.
foreach (TestObject test in Tests)
{
test.RunTest()
}
//This is in the TestObject class
RunTest()
{
if (failure)
{
//Want to be able to run RunTest() again without interrupting the foreach loop.
}
}
You guys like too much code...
for (var tryCount = 0; tryCount < 3; tryCount++)
if (test.RunTest())
break;
... oh I thought of an even shorter version... but it's not as clean ...
for (var tryCount = 0; !test.RunTest() && tryCount < 3; tryCount++);
If you want reuse then something like this...
static bool RunTest(Func<bool> testCase, int maxRetry)
{
for (var tryCount = 0; tryCount < maxRetry; tryCount++)
if (testCase())
return true;
return false;
}
// usage
var testResult = RunTest(test.RunTest, 3);
// or even...
var testResult = RunTest(
{
try {
return test.RunTest();
} catch (Exception ex) {
Debug.WriteLine(ex);
return false;
}
}, 3);
For both answers above, the solutions will result in RunTest() running forever if the failure is legitimate (i.e. not a transient failure, which I can only guess is what you're hitting). You may consider doing one of the loops above, but instead keep a count of how many failures and bail out once that threshold is reached. Something like:
int FailureThreshold = 3;
foreach (TestObject test in Tests)
{
int failCount = 0;
while (failCount < FailureThreshold)
{
if (test.RunTest())
{
break;
}
else
{
failCount++;
}
}
}
You should also consider keeping statistics for how many times you need to loop in order to pass. This could be a great indicator of test stability.
There are several ways you could go about doing this, depending on why exactly you want to do this. You could:
1) Have RunTest() return boolean for success or failure, and then:
foreach (TestObject test in Tests)
{
while(!test.runTest(){}
}
2) Use a while inside of RunTest():
RunTest()
{
while(true)
{
...test stuff...
if(failure)
continue;
else
break;
}
}
foreach (TestObject test in Tests)
{
test.RunTest()
}
//This is in the TestObject class
RunTest()
{
//set it to failure or set variable to failure
while (failure)
{
//do the test
//if using variable set it to failure if it failed, success if it succeeded
//will keeping going through the while statement until it succeeds or you cut it off another way
}
// has succeeded
}