How to check whether a string can be casted to be Long ?

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I need to read data from serialport and then cast them to Long by using vb
..net on Ce device. Sometimes I will have InvalidCastException. How can I
make sure the string can be cast long before I do it in order to prevent the
InvalidCastException?
 
Thanks for reply.

I already do that but my problem is it makes the software run slower or even
paused for a little while when exception occur while my application has to
process 10 data per second real time. So I really wants to check the string
before I cast it in order to prevent the invalidcastexception.

Kempton
 
Hmm, perhaps this is different on a PC than on a PDA, but all my tests show
that exceptions slow down quite a lot, regardless if you are running under
debugger or optimized release version. My test was done on a PC and it's a
release version of the test application.

Worth noting is that when increasing the number of lines (10times the
previous test) tested in a testrun, the time to run the test without
exceptions increased by a factor 2, while the test with exceptions increased
by a factor 10.

Below is the code and the testresults.

The results (strings = number of strings casted, OK = no exception, Exc =
Exception was thrown, Ticks=total amount of ticks for the testrun):
Strings: 1000, OK = 1000, Exc = 0 Ticks: 0
Strings: 1000, OK = 1000, Exc = 0 Ticks: 0
Strings: 1000, OK = 0, Exc = 1000 Ticks: 63
Strings: 1000, OK = 0, Exc = 1000 Ticks: 47
Strings: 1000, OK = 0, Exc = 1000 Ticks: 47
Strings: 10000, OK = 10000, Exc = 0 Ticks: 0
Strings: 10000, OK = 10000, Exc = 0 Ticks: 16
Strings: 10000, OK = 10000, Exc = 0 Ticks: 16
Strings: 10000, OK = 10000, Exc = 0 Ticks: 15
Strings: 10000, OK = 0, Exc = 10000 Ticks: 422
Strings: 10000, OK = 0, Exc = 10000 Ticks: 438
Strings: 10000, OK = 0, Exc = 10000 Ticks: 422
Strings: 10000, OK = 0, Exc = 10000 Ticks: 407
Strings: 100000, OK = 100000, Exc = 0 Ticks: 31
Strings: 100000, OK = 100000, Exc = 0 Ticks: 31
Strings: 100000, OK = 100000, Exc = 0 Ticks: 32
Strings: 100000, OK = 100000, Exc = 0 Ticks: 32
Strings: 100000, OK = 0, Exc = 100000 Ticks: 4141
Strings: 100000, OK = 0, Exc = 100000 Ticks: 4141
Strings: 100000, OK = 0, Exc = 100000 Ticks: 4203
Strings: 100000, OK = 3, Exc = 99997 Ticks: 4172

The code (this is for PC appliaction) not CF!!:
using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.IO;

using System.Text;

namespace WinTestOvrFlwExcSpeed

{

/// <summary>

/// Summary description for Form1.

/// </summary>

public class Form1 : System.Windows.Forms.Form

{

private System.Windows.Forms.TextBox textBox2;

private System.Windows.Forms.CheckBox checkBox1;

private System.Windows.Forms.Button button1;

private System.Windows.Forms.TextBox textBox1;

private System.Windows.Forms.Label label1;

private System.Windows.Forms.Label label2;

private System.Windows.Forms.TextBox txtOutputFileName;

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

public Form1()

{

//

// Required for Windows Form Designer support

//

InitializeComponent();

//

// TODO: Add any constructor code after InitializeComponent call

//


}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{

this.textBox2 = new System.Windows.Forms.TextBox();

this.checkBox1 = new System.Windows.Forms.CheckBox();

this.button1 = new System.Windows.Forms.Button();

this.textBox1 = new System.Windows.Forms.TextBox();

this.txtOutputFileName = new System.Windows.Forms.TextBox();

this.label1 = new System.Windows.Forms.Label();

this.label2 = new System.Windows.Forms.Label();

this.SuspendLayout();

//

// textBox2

//

this.textBox2.Location = new System.Drawing.Point(16, 8);

this.textBox2.MaxLength = 3276700;

this.textBox2.Multiline = true;

this.textBox2.Name = "textBox2";

this.textBox2.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;

this.textBox2.Size = new System.Drawing.Size(384, 304);

this.textBox2.TabIndex = 3;

this.textBox2.Text = "";

//

// checkBox1

//

this.checkBox1.Location = new System.Drawing.Point(296, 320);

this.checkBox1.Name = "checkBox1";

this.checkBox1.TabIndex = 4;

this.checkBox1.Text = "With exceptions";

//

// button1

//

this.button1.Location = new System.Drawing.Point(296, 352);

this.button1.Name = "button1";

this.button1.TabIndex = 5;

this.button1.Text = "Test";

this.button1.Click += new System.EventHandler(this.button1_Click);

//

// textBox1

//

this.textBox1.Location = new System.Drawing.Point(120, 344);

this.textBox1.Name = "textBox1";

this.textBox1.Size = new System.Drawing.Size(88, 20);

this.textBox1.TabIndex = 6;

this.textBox1.Text = "1000";

//

// txtOutputFileName

//

this.txtOutputFileName.Location = new System.Drawing.Point(120, 320);

this.txtOutputFileName.Name = "txtOutputFileName";

this.txtOutputFileName.Size = new System.Drawing.Size(168, 20);

this.txtOutputFileName.TabIndex = 7;

this.txtOutputFileName.Text = "output.txt";

//

// label1

//

this.label1.Location = new System.Drawing.Point(20, 320);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(96, 20);

this.label1.TabIndex = 8;

this.label1.Text = "Save output to:";

this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;

//

// label2

//

this.label2.Location = new System.Drawing.Point(16, 344);

this.label2.Name = "label2";

this.label2.Size = new System.Drawing.Size(100, 20);

this.label2.TabIndex = 9;

this.label2.Text = "Repeat:";

this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;

//

// Form1

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.ClientSize = new System.Drawing.Size(416, 382);

this.Controls.Add(this.label2);

this.Controls.Add(this.label1);

this.Controls.Add(this.txtOutputFileName);

this.Controls.Add(this.textBox1);

this.Controls.Add(this.textBox2);

this.Controls.Add(this.checkBox1);

this.Controls.Add(this.button1);

this.Name = "Form1";

this.Text = "Form1";

this.ResumeLayout(false);

}

#endregion

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main()

{

Application.Run(new Form1());

}

private bool ValueWithinRange( string strInt )

{

try

{

int iTmp = Convert.ToInt32(strInt);

if( iTmp > int.MaxValue || iTmp < int.MinValue )

return false;

else

return true;

}

catch( OverflowException )

{

return false;

}

}

private void button1_Click(object sender, System.EventArgs e)

{

double dTicksStart, dTicksEnd;

int iNumStrings = Convert.ToInt32(this.textBox1.Text);

string[] strChar = new string[iNumStrings];

System.Random rnd = new Random();


for( int i = 0; i<iNumStrings; i++)

{

int r = rnd.Next();

string strSingle = Convert.ToString(r);

string strDouble = Convert.ToString(r) +
Convert.ToString(r);///50000000000);

if( !checkBox1.Checked )

strChar = strSingle;

else

strChar = strDouble;


}

dTicksStart = Environment.TickCount;

int iOk = 0, iXX = 0;

for(int i = 0; i<iNumStrings; i++)

{

if( ValueWithinRange( strChar ) )

iOk++;

else

iXX++;

}

dTicksEnd = Environment.TickCount;

double res = dTicksEnd - dTicksStart;


textBox2.Text += "Strings: " + iNumStrings.ToString() +

", OK = " + iOk.ToString() +

", Exc = " + iXX.ToString() +

" Ticks: " + res.ToString() + "\r\n";

string file = this.txtOutputFileName.Text;

StreamWriter sw;

using( sw = new StreamWriter( file, false, Encoding.Unicode ) )

{

foreach( string line in textBox2.Lines )

{

sw.WriteLine( line );

}

}


}

}

}
 
Ignore the "Worth noting" text in my message. When testing on significantly
more lines, the no-exception tests increase by a factor 10 as well..

regards,

Peter
 
PeterB said:
Hmm, perhaps this is different on a PC than on a PDA, but all my tests show
that exceptions slow down quite a lot, regardless if you are running under
debugger or optimized release version. My test was done on a PC and it's a
release version of the test application.

Throwing an exception is certainly more expensive than not throwing an
exception, but the problems associated with them are usually *vastly*
overstated. Most tests for exception performance are, like yours,
comparing the situation where you're doing virtually nothing *but*
throwing exceptions with a situation where you're doing virtually
nothing. That doesn't model real-world experience. Yes, if you're in a
situation where everything you do will throw an exception, exception
performance will kill you. In most situations, however, that's not the
case - usually very few values are actually invalid, and the exception
hit is pretty much lost in the noise.

As an example of this type of view gone mad, there was a question in
the performance group a while ago about whether or not a few thousand
exceptions thrown in an hour was hurting the OP's performance. Many
people jumped on this and said that yes, indeed, a few thousand
exceptions would be killing performance. In fact, my laptop can throw a
hundred thousand exceptions in a second, so a few thousand exceptions
would only be taking a *tiny* proportion of the total time. There are
usually far better reasons for not throwing thousands of exceptions
than performance.

I don't remember *ever* running into a performance bottleneck which was
due to exceptions. I'm sure they happen, but not often enough to
justify the paranoia which seems to surround them.
 
True so true!

All I wanted to prove with my test was that exceptions does "cost" even if
your program is running on optimized code.

I re-did the test and only threw an exception on ~10% of the casts. There is
ofc. a significant improvment to performance. Remember though that a Windowc
CE device are more likely to get a perfomance bottleneck than a PC.

For instance, there definitely is a slight "freeze" the first time an
exception is created (comes with the .NET world I guess), and perhaps this
is what Kempton sees.

So back to the original question, is there any way to prevent the Exception
from beeing thrown in the first place?

There is a function double.TryParse(...) (in C# dunno about VB...), I don't
know what it's internal code does but it doesn't throw an exception :-), and
the name of it sounds promising, perhaps it could be of use? On the other
hand, this would add another function call to the code...

regards,

Peter
 
PeterB said:
True so true!

All I wanted to prove with my test was that exceptions does "cost" even if
your program is running on optimized code.

I certainly agree with that.
I re-did the test and only threw an exception on ~10% of the casts. There is
ofc. a significant improvment to performance. Remember though that a Windowc
CE device are more likely to get a perfomance bottleneck than a PC.

Not sure about that. A bottleneck is really about the proportion of
time spent doing one thing compared with another - and if
*everything's* just (say) 5 times slower on Pocket PC than on the
desktop, exceptions wouldn't become a bottleneck particularly. Depends
on your view of bottlenecks though.
For instance, there definitely is a slight "freeze" the first time an
exception is created (comes with the .NET world I guess), and perhaps this
is what Kempton sees.

Interesting. I'm used to seeing that in a debugger for the desktop
world - haven't particularly looked on the CF for that in particular
though.
So back to the original question, is there any way to prevent the Exception
from beeing thrown in the first place?

There is a function double.TryParse(...) (in C# dunno about VB...), I don't
know what it's internal code does but it doesn't throw an exception :-), and
the name of it sounds promising, perhaps it could be of use? On the other
hand, this would add another function call to the code...

If performance is definitely an issue, using some hand-crafted code to
get rid of most invalid values makes a *huge* difference.

See a thread in the .framework group, entitled "Checking if a string
can be converted to Int32" for some sample code and eye-catching
results.
 
Thinking about it, Alex may be "more or less right" after all ( as usual
;-) ).

As John explains, exceptions are more costly but very much overstated.
Running the code in debugger does slow the application down so much that
exceptions beeing thrown is really "showing off". If run with optimized code
without debugger there is a great performance improvement and you will most
likely not see the "hickups" you experience (or atleast not as noticably) as
when run in debug mode.

Also, the TryParse wouldn't work since you are converting a long and not a
double.

regards,

Peter


PeterB said:
True so true!

All I wanted to prove with my test was that exceptions does "cost" even if
your program is running on optimized code.

I re-did the test and only threw an exception on ~10% of the casts. There
is ofc. a significant improvment to performance. Remember though that a
Windowc CE device are more likely to get a perfomance bottleneck than a
PC.

For instance, there definitely is a slight "freeze" the first time an
exception is created (comes with the .NET world I guess), and perhaps this
is what Kempton sees.

So back to the original question, is there any way to prevent the
Exception from beeing thrown in the first place?

There is a function double.TryParse(...) (in C# dunno about VB...), I
don't know what it's internal code does but it doesn't throw an exception
:-), and the name of it sounds promising, perhaps it could be of use? On
the other hand, this would add another function call to the code...

regards,

Peter
 
Nice Benchmark framework :-)

Might come in handy!

Too bad GUI benchmarking is such a pain in the ***.

regards,

Peter
 
Back
Top