I'm in my second quarter of c # programming and i'm working on a POS application. I have my windows form created and I have my basic code done for the first week it was assigned. Now I have to "idiot-proof" my code by making sure that only correct data can be entered. Here's what I have so far:
private void btnAddItem_Click(object sender, EventArgs e)
{
//Declare variables
double dblSalesTax = 0, dblPrice, dblTax, dblSalesPrice;
string strItem, strTaxAdded;
int intQuantity;
bool diffTest = false;
//Process user input
while (!diffTest)
{
diffTest = double.TryParse(txtSalesTax.Text, out dblSalesTax);
}
while (dblSalesTax < 0 || dblSalesTax > 25)
{
MessageBox.Show("Please enter a valid tax.");
txtSalesTax.Clear();
diffTest = false;
}
intQuantity = Convert.ToInt16(txtQuantity.Text);
dblPrice = Convert.ToDouble(txtPrice.Text);
dblSalesPrice = dblPrice * intQuantity;
strItem = cbxItem.Text;
intQuantity = Convert.ToInt16(txtQuantity.Text);
dblSubtotal += dblSalesPrice;
if (chkTaxExempt.Checked)
{
dblTax = 0;
strTaxAdded = "";
}
else
{
dblTax = dblSalesPrice * dblSalesTax;
strTaxAdded = "*";
}
dblTaxTotal += dblTax;
lbxTally.Items.Add(strItem + ", " + dblSalesPrice.ToString("C") + strTaxAdded);
//Reset Form
txtPrice.Clear();
txtQuantity.Clear();
chkTaxExempt.Checked = false;
cbxItem.Focus();
}
private void btnEndSale_Click(object sender, EventArgs e)
{
dblGrandTotal = dblSubtotal + dblTaxTotal;
lbxTally.Items.Add("");
lbxTally.Items.Add("");
lbxTally.Items.Add("Subtotal: " + dblSubtotal.ToString("C"));
lbxTally.Items.Add("Tax Total: " + dblTaxTotal.ToString("C"));
lbxTally.Items.Add("Grand Total: " + dblGrandTotal.ToString("C"));
}
private void btnPay_Click(object sender, EventArgs e)
{
double dblPay, dblChange;
dblPay = Convert.ToDouble(txtPay.Text);
dblChange = dblPay - dblGrandTotal;
lbxTally.Items.Add("");
lbxTally.Items.Add("Amount Paid: " + dblPay.ToString("C"));
lbxTally.Items.Add("Change: " + dblChange.ToString("C"));
}
Variables being declared beforehand and diffTest being initialized as false.
The assignment is to make sure that the sales tax entered is between 0 and 25 and that they can't enter words or anything else. I thought I did it right but when I run it, I have an infinite loop on my message box and I can't figure out how to get out of it correctly (entering break just gets me out but keeps the input). I have google'd to my hearts content but haven't found a solution but I feel like it's because my code is reusing what's in the text box automatically (I could be very wrong!). Once I get this i'll have to "idiot-proof" my other inputs but I haven't tried yet cause I'm still stuck on this first one. I'm a beginner programming student so any help is appreciated.
You don't need a while statement there. Change it to:
if (dblSalesTax < 0 || dblSalesTax > 25)
Because you have there a while loop as soon as you step into that loop you will never get out because your condition will be always true.
My guess is that you should change While to If.
private void btnAddItem_Click(object sender, EventArgs e)
{
//Declare variables
double dblSalesTax = 0, dblPrice, dblTax, dblSalesPrice;
string strItem, strTaxAdded;
int intQuantity;
bool diffTest = false;
//Process user input
//While (!diffTest)
//{
diffTest = double.TryParse(txtSalesTax.Text, out dblSalesTax);
//}
// Check if the value gets parsed and is in range, otherwise show error and
//exit from this handler
If (!diffTest || dblSalesTax < 0 || dblSalesTax > 25) '<--- Change While to If
{
MessageBox.Show("Please enter a valid tax.");
txtSalesTax.Clear();
diffTest = false;
return; // Return from here since validation failed
}
...
...
...
}
May you can try using Parallel.Invoke(() => DoSomeWork(), () => DoSomeOtherWork()); withawait for the the task that has your loop, something like below:
Parallel.Invoke(
() =>
{
Console.WriteLine("Begin first task...");
}, // close first Action
async () =>
{
Console.WriteLine("Begin second task...");
while (true)
{
// HERE you are the code you need to be executed in infinite loop
await Task.Delay(60000);
}
}, //close second Action
() =>
{
Console.WriteLine("Begin third task...");
} //close third Action
); //close parallel.invoke
Console.WriteLine("Returned from Parallel.Invoke");
Related
public partial class frmEnhancedInvoiceTotal : Form
{
public frmEnhancedInvoiceTotal()
{
InitializeComponent();
}
private void BtnExit_Click(object sender, EventArgs e)
{
Close();
}
decimal[] decTotalofInvoicesArray = new decimal[5];
int intNumberOfInvoices = 0; //global variables
decimal decTotalOfInvoicesVariable = 0m;
decimal decAverageOfInvoices = 0m;
private void BtnCalculate_Click(object sender, EventArgs e)
{
//Convert = Class, .ToDecimal = method,
//when the user clicks the calulate button,
//we collect the subtotal, determine the appropriate discount,
//calculate the total and output the result to the screen.
//***EARN PARTIAL CREDIT PUT COMMENTS***
//Input
try
{
decimal decSubtotal = 0m; //initialize subtotal with a value of zero. We'll collect from the user later.
if (Decimal.TryParse(txtSubtotal.Text,
System.Globalization.NumberStyles.Currency, //now can type a $ sign and now break the code
System.Globalization.CultureInfo.CurrentCulture,
out decSubtotal)) //.tryparse attempts to convert but is a fail safe
//parse does 2 things - does something and tells you if works
decTotalofInvoicesArray[intNumberOfInvoices] = decSubtotal;
{
//Processing
decimal decDiscountPercent = 0m; //defining a new variable (discount percent) allow for real #, giving it a intial value of 0. Decimal variables you have to add m
if (decSubtotal >= 500m) //if my subtotal is 500 or more
{
decDiscountPercent = 0.2m; //inside braces is what will happen to the question above
//set discount rate to 20%
}
else if (decSubtotal < 500m && decSubtotal >= 250m) //if subtotal is between 250 & 500
//^^redundant because < 500 is already stated in the first if statement
//could just right else if(decSubtotal >=250m)
{
decDiscountPercent = 0.15m; //set discount rate to 15%
}
else if (decSubtotal < 250m && decSubtotal >= 100m) //if subtotal is between 100 and 250
{
decDiscountPercent = 0.1m; //set discount to 10%
}
//if subtotal is less than 100, dicounter percent is 0%
decimal decDiscountAmount = decDiscountPercent * decSubtotal;
decimal decTotal = decSubtotal - decDiscountAmount; //He is going so fast
//Aggregate Processing - across mutliple clicks of the calculate button
//old way of doing it = intNumberOfInvoices = intNumberOfInvoices + 1;
intNumberOfInvoices++; //value of variable plus one
//old way of doing it decTotalOfInvoices = decTotalOfInvoices + decTotal;
decimal decSum = 0m;
for (int intColIndex = 0; intColIndex < decTotalofInvoicesArray.Length; intColIndex++)
{
decSum += decTotalofInvoicesArray[intColIndex];
}
decTotalOfInvoicesVariable = decSum;
decAverageOfInvoices = decSum / decTotalofInvoicesArray.Length;
//Output
txtSubtotal.Text = decSubtotal.ToString("c");
txtDiscountPercent.Text = decDiscountPercent.ToString("p2"); //sending a numeric value and sending it to text = gives error
txtDiscountAmount.Text = decDiscountAmount.ToString("c"); //dot ToString makes value a text value and sends to textbox in form
//c=currency //"p2" - 2 = how many decimal places
//P = percentage
txtTotal.Text = decTotal.ToString("c");
//aggregate output
txtNumberOfInvoices.Text = intNumberOfInvoices.ToString();
txtTotalOfInvoices.Text = decTotalOfInvoicesVariable.ToString("c");
txtAverageOfInvoices.Text = decAverageOfInvoices.ToString("c");
//breakpoint analysis = click on the grey side bar and slowly work through the code to find the error. Essentially pause the code and run the code one point at a time
}
}
catch (FormatException) //you do not know what went wrong in the try part. It just errors anyways because SOMETHING went wrong
{
MessageBox.Show("Please enter valid numeric values.", "Entry Error");
}
catch (OverflowException) //something is to big
{
MessageBox.Show("Please try smaller numbers", "Entry Error");
}
catch //generic error code because why not
{
MessageBox.Show("An unexpected error has occured. Please try again.", "Entry Error");
}
}
private void BtnClearTotals_Click(object sender, EventArgs e)
{
//When resetting aggregate/global info - need to reset the variables AND the visual interface
intNumberOfInvoices = 0;
decTotalOfInvoicesVariable = 0m;
decAverageOfInvoices = 0m;
// txtNumberOfInvoices.Text = ""; //setting the variable to nothing. Erase the information in the text box
txtNumberOfInvoices.Clear();
txtTotalOfInvoices.Clear();
txtAverageOfInvoices.Clear();
}
private void TxtSubtotal_TextChanged(object sender, EventArgs e)
{
txtDiscountPercent.Clear();
txtDiscountAmount.Clear();
txtTotal.Clear();
}
private void BtnDisplayTotals_Click(object sender, EventArgs e)
{
String strOrderTotals = "";
//for (int intColIndex = 0; intColIndex < intNumberOfInvoices; intColIndex++)
//{
// strOrderTotals += decTotalofInvoicesArray[intColIndex] + "\n";
//}
foreach (decimal decTotalInvoices in decTotalofInvoicesArray)
{
if (strOrderTotals == "0")
{
strOrderTotals += decTotalInvoices + "\n";
}
}
MessageBox.Show(strOrderTotals.ToString());
}
private bool IsValidData()
{
return
IsPresent(txtSubtotal) && //did you type anyting
IsDecimal(txtSubtotal) && //make sure you types a real number
IsWithinRange(txtSubtotal, 0m, 1000m); //is the number in the range
}
private bool IsPresent(TextBox textBox) //send an entire textbox into method
{
if (textBox.Text == "")
{
MessageBox.Show(textBox.Tag.ToString() + " is a required field.", "Missing Entry"); //textbox is whatever is in the (TextBox textBox)
textBox.Focus();
return false;
}
return true;
}
private bool IsDecimal(TextBox textBox)
{
decimal decTestValue = 0m;
if (!Decimal.TryParse(textBox.Text, out decTestValue)) //! - dont succusfully tryparse
{
MessageBox.Show(textBox.Tag.ToString() + " must be a numeric value", "Entry Error"); //textbox is whatever is in the (TextBox textBox)
textBox.Focus();
return false;
}
return true;
}
private bool IsInteger(TextBox textBox)
{
int intTestValue = 0;
if (!Int32.TryParse(textBox.Text, out intTestValue)) //! - dont succusfully tryparse
{
MessageBox.Show(textBox.Tag.ToString() + " must be a whole number.", "Missing Entry"); //textbox is whatever is in the (TextBox textBox)
textBox.Focus();
return false;
}
return true;
}
private bool IsWithinRange(TextBox textBox, decimal decMin, decimal decMax)
{
decimal decTestValue = Convert.ToDecimal(textBox.Text);
if (decTestValue < decMin || decTestValue > decMax) //to small or to big
{
MessageBox.Show(textBox.Tag.ToString() + " must be between " + decMin.ToString() + " and " + decMax.ToString() + "." + "Out of Range"); //textbox is whatever is in the (TextBox textBox)
textBox.Focus();
return false;
}
return true;
}
}
}
Basically I have a invoice total windows form were the user inputs a subtotal value and total value is calculated based on the discount percent. In the assignment is says to create an array that hold up to five invoice totals. My problem is when I type lets say 2 subtotal values and click display totals the 2 number I typed in are displayed along with 3 zeros. I am wanting to know how to only display the number I inputted and not the zeros using a foreach loop.
It does not look like you are adding anything in your foreach.
foreach (decimal decTotalInvoices in decTotalofInvoicesArray)
{
if (strOrderTotals == "0")
{
strOrderTotals += decTotalInvoices + "\n";
}
}
MessageBox.Show(strOrderTotals.ToString());
Am I reading this right that you want to have each invoice shown, and do you want the total too? This code with a for loop should work. I
strOrderTotals = "My Invoices\n";
decimal decOrderTotals = 0;
for (int i = 0; i < decTotalofInvoicesArray.Length; i++)
{
if (decTotalofInvoicesArray[i] != 0)
{
strOrderTotals += "Invoice : " + decTotalofInvoicesArray[i] + "\n";
decOrderTotals += decTotalofInvoicesArray[i];
}
}
strOrderTotals += "Total of invoices: " + decOrderTotals;
MessageBox.Show(strOrderTotals.ToString());
I have a variable 'start' that initializes with a value 0.
How can i switch to a different loop when 1 argument becomes true.
So here is what i am trying to accomplish
when I click the button
1st Loop start with textBlock 1 containing "XXXX"
and Variable'Start' increment's by 1 everytime i click/touch till it reaches 34 . So when the counter reaches 34, the text changes to 'YYYY'
2nd Loop is when the counter resets and starts from 0 again but this time it only needs to go up till 33 . As soon as it reaches 33 the text changes to 'ZZZZ'.
Last Loop: The counter resets agains goes up till 33 . But this time when it finishes. It goes back to loop 1.
Here is the code that i have right now and I cannot seem to figure out how to do the last loop.
public partial class MainPage : PhoneApplicationPage
{
private int start = 0;
private bool sw = false;
// Constructor
public MainPage()
{
InitializeComponent();
int start = 0;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
tasbih();
}
public void tasbih()
{
if (sw == false)
{
textBlock1.Text = "TEXTBX 1";
}
start++;
String text1 = Convert.ToString(start);
textBlock2.Text = text1;
if (start >= 35)
{
textBlock1.Text = "TEXTBX 2";
start = 0;
String text2 = Convert.ToString(start);
textBlock2.Text = text2;
sw = true;
}
}
private void button2_Click(object sender, RoutedEventArgs e)
{
textBlock1.Text = "Reset";
tasbih();
}
Also i have a reset button that starts everything all over no matter where you are in the counter. Any pointers as to how i can do that ?
I suggest you have a more explicit state variable, and key off of that for all your logic. You're currently keying off of start only for the transition to sw = true, it'll be easier if you have an explicit state.
enum MyState { Part1, Part2, Part3 }
MyState currentState = Part1;
int clickCount = 0;
public void tasbih()
{
clickCount++;
// First, do state transitions.
switch(currentState)
{
case MyState.Part1:
if(clickCount >= 34) { currentState = MyState.Part2; clickCount = 0; }
break;
case MyState.Part2:
if(clickCount >= 33) { currentState = MyState.Part3; clickCount = 0; }
break;
case MyState.Part3:
if(clickCount >= 33) { currentState = MyState.Part1; clickCount = 0; }
break;
}
// Now, act on the current (or new) state.
switch(currentState)
{
case MyState.Part1:
textBlock1.Text = "TEXTBX 1";
textBlock2.Text = clickCount.ToString();
break;
case MyState.Part2:
textBlock1.Text = "TEXTBX 2";
textBlock2.Text = clickCount.ToString();
break;
case MyState.Part3:
textBlock1.Text = "ZZZZ";
textBlock2.Text = clickCount.ToString();
break;
}
}
private void button2_Click(object sender, RoutedEventArgs e)
{
currentState = MyState.Part1;
clickCount = 0;
tasbih();
}
// these have to be member variables, or you'll never be able to reset
// or even remember the counter between calls
private int clicks = 0; // the number of clicks in the current loop
private int state = 0; // which loop we're in
// these are just so we don't have to repeat ourselves.
// each element corresponds to a possible value of `state`.
// both arrays should have the same number of elements.
// alternatively, you could have a type containing the label and max together,
// and just have an array of those.
private string[] labels = { "TEXTBX 1", "TEXTBX 2", "ZZZZ" };
private int[] max = { 34, 33, 33 };
public void reset() {
clicks = 0;
state = 0;
// probably reset text boxes here too. If you don't want to, then delete
updateTextBoxes();
}
public void bump()
{
// bump the counter, and if it's high enough, switch to the next state
// and reset the counter
// (the "% max.Length" causes 3 to be 0, so states wrap around)
if (++clicks > max[state])
{
state = (state + 1) % max.Length;
clicks = 0;
}
updateTextBoxes();
}
private void updateTextBoxes() {
textBlock1.Text = labels[state];
textBlock2.Text = clicks.ToString();
}
I am writing a WinForm application to use SNMP calls either every 30 seconds or 1 minute.
I have a timer working for calling my SNMP commands, but I want to add a texbox counter that display the total time elapsed during the operation.
There are many problems I am having so here is a list:
I want my SNMP timer 'timer' to execute once before waiting the allotted time so I have it going off at 3 seconds and then changing the interval in my handler. But this sometimes makes the timer go off multiple times which is not what I want.
Every time 'timer' goes off and my SNMP calls execute my counter timer 'appTimer' becomes out of sync. I tried a work around where I check if it is in the other handler and then just jump the timer to its appropriate time. Which works but I feel this is making it too complicated.
My last issue, that I know of, happens when I stop my application using my stop button which does not completely exit the app. When I go to start another run the time between both timers is becomes even greater and for some reason my counting timer 'appTimer' starts counting twice as fast.
I hope this description isn't too confusing but here is my code anyway:
using System;
using System.Net;
using SnmpSharpNet;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public static bool stop = false;
static bool min = true, eye = false, firstTick = false;
static string ipAdd = "", fileSaveLocation = "";
static System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
static System.Windows.Forms.Timer appTimer = new System.Windows.Forms.Timer();
static int alarmCounter = 1, hours = 0, minutes = 0, seconds = 0, tenthseconds = 0, count = 0;
static bool inSNMP = false;
static TextBox textbox, timeTextbox;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
textbox = outputBox;
timeTextbox = timeBox;
ipAdd = "192.168.98.107";
fileSaveLocation = "c:/Users/bshellnut/Desktop/Eye.txt";
min = true;
inSNMP = false;
}
private void IPtext_TextChanged(object sender, EventArgs e)
{
ipAdd = IPtext.Text;
}
private void stopButton_Click(object sender, EventArgs e)
{
stop = true;
timer.Stop();
appTimer.Stop();
count = 0;
hours = minutes = seconds = tenthseconds = 0;
inSNMP = false;
}
// This is the method to run when the timer is raised.
private static void TimerEventProcessor(Object myObject,
EventArgs myEventArgs)
{
inSNMP = true;
timer.Stop();
if (firstTick == true)
{
// Sets the timer interval to 60 seconds or 1 second.
if (min == true)
{
timer.Interval = 1000 * 60;
}
else
{
timer.Interval = 1000 * 30;
}
}
// Displays a message box asking whether to continue running the timer.
if (stop == false)
{
textbox.Clear();
// Restarts the timer and increments the counter.
alarmCounter += 1;
timer.Enabled = true;
System.IO.StreamWriter file;
//if (eye == true)
//{
file = new System.IO.StreamWriter(fileSaveLocation, true);
/*}
else
{
file = new System.IO.StreamWriter(fileSaveLocation, true);
}*/
// SNMP community name
OctetString community = new OctetString("public");
// Define agent parameters class
AgentParameters param = new AgentParameters(community);
// Set SNMP version to 2 (GET-BULK only works with SNMP ver 2 and 3)
param.Version = SnmpVersion.Ver2;
// Construct the agent address object
// IpAddress class is easy to use here because
// it will try to resolve constructor parameter if it doesn't
// parse to an IP address
IpAddress agent = new IpAddress(ipAdd);
// Construct target
UdpTarget target = new UdpTarget((IPAddress)agent, 161, 2000, 1);
// Define Oid that is the root of the MIB
// tree you wish to retrieve
Oid rootOid;
if (eye == true)
{
rootOid = new Oid("1.3.6.1.4.1.128.5.2.10.14"); // ifDescr
}
else
{
rootOid = new Oid("1.3.6.1.4.1.128.5.2.10.15");
}
// This Oid represents last Oid returned by
// the SNMP agent
Oid lastOid = (Oid)rootOid.Clone();
// Pdu class used for all requests
Pdu pdu = new Pdu(PduType.GetBulk);
// In this example, set NonRepeaters value to 0
pdu.NonRepeaters = 0;
// MaxRepetitions tells the agent how many Oid/Value pairs to return
// in the response.
pdu.MaxRepetitions = 5;
// Loop through results
while (lastOid != null)
{
// When Pdu class is first constructed, RequestId is set to 0
// and during encoding id will be set to the random value
// for subsequent requests, id will be set to a value that
// needs to be incremented to have unique request ids for each
// packet
if (pdu.RequestId != 0)
{
pdu.RequestId += 1;
}
// Clear Oids from the Pdu class.
pdu.VbList.Clear();
// Initialize request PDU with the last retrieved Oid
pdu.VbList.Add(lastOid);
// Make SNMP request
SnmpV2Packet result;
try
{
result = (SnmpV2Packet)target.Request(pdu, param);
}
catch (SnmpSharpNet.SnmpException)
{
timer.Stop();
textbox.Text = "Could not connect to the IP Provided.";
break;
}
// You should catch exceptions in the Request if using in real application.
// If result is null then agent didn't reply or we couldn't parse the reply.
if (result != null)
{
// ErrorStatus other then 0 is an error returned by
// the Agent - see SnmpConstants for error definitions
if (result.Pdu.ErrorStatus != 0)
{
// agent reported an error with the request
textbox.Text = "Error in SNMP reply. " + "Error " + result.Pdu.ErrorStatus + " index " + result.Pdu.ErrorIndex;
lastOid = null;
break;
}
else
{
// Walk through returned variable bindings
foreach (Vb v in result.Pdu.VbList)
{
// Check that retrieved Oid is "child" of the root OID
if (rootOid.IsRootOf(v.Oid))
{
count++;
textbox.Text += "#" + count + " " + v.Oid.ToString() + " " + SnmpConstants.GetTypeName(v.Value.Type) +
" " + v.Value.ToString() + Environment.NewLine;
file.WriteLine("#" + count + ", " + v.Oid.ToString() + ", " + SnmpConstants.GetTypeName(v.Value.Type) +
", " + v.Value.ToString(), true);
if (v.Value.Type == SnmpConstants.SMI_ENDOFMIBVIEW)
lastOid = null;
else
lastOid = v.Oid;
}
else
{
// we have reached the end of the requested
// MIB tree. Set lastOid to null and exit loop
lastOid = null;
}
}
}
}
else
{
//Console.WriteLine("No response received from SNMP agent.");
textbox.Text = "No response received from SNMP agent.";
//outputBox.Text = "No response received from SNMP agent.";
}
}
target.Close();
file.Close();
}
else
{
// Stops the timer.
//exitFlag = true;
count = 0;
}
}
private static void ApplicationTimerEventProcessor(Object myObject,
EventArgs myEventArgs)
{
tenthseconds += 1;
if (tenthseconds == 10)
{
seconds += 1;
tenthseconds = 0;
}
if (inSNMP && !firstTick)
{
if (min)
{
seconds = 60;
}
else
{
textbox.Text += "IN 30 SECONDS!!!";
if (seconds < 30)
{
seconds = 30;
}
else
{
seconds = 60;
}
}
}
if(seconds == 60)
{
seconds = 0;
minutes += 1;
}
if(minutes == 60)
{
minutes = 0;
hours += 1;
}
timeTextbox.Text = (hours < 10 ? "00" + hours.ToString() : hours.ToString()) + ":" +
(minutes < 10 ? "0" + minutes.ToString() : minutes.ToString()) + ":" +
(seconds < 10 ? "0" + seconds.ToString() : seconds.ToString()) + "." +
(tenthseconds < 10 ? "0" + tenthseconds.ToString() : tenthseconds.ToString());
inSNMP = false;
firstTick = false;
}
private void eyeButton_Click(object sender, EventArgs e)
{
outputBox.Text = "Connecting...";
eye = true;
stop = false;
count = 0;
hours = minutes = seconds = tenthseconds = 0;
timer.Tick += new EventHandler(TimerEventProcessor);
timer.Interval = 3000;
firstTick = true;
appTimer.Tick += new EventHandler(ApplicationTimerEventProcessor);
appTimer.Interval = 100;
appTimer.Start();
timer.Start();
}
private void jitterButton_Click(object sender, EventArgs e)
{
outputBox.Text = "Connecting...";
eye = false;
stop = false;
count = 0;
hours = minutes = seconds = tenthseconds = 0;
timer.Tick += new EventHandler(TimerEventProcessor);
timer.Interval = 3000;
firstTick = true;
appTimer.Tick += new EventHandler(ApplicationTimerEventProcessor);
appTimer.Interval = 100;
appTimer.Start();
timer.Start();
}
private void Seconds_CheckedChanged(object sender, EventArgs e)
{
min = false;
}
private void Minutes_CheckedChanged(object sender, EventArgs e)
{
min = true;
}
private void exitButton_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void savetextBox_TextChanged(object sender, EventArgs e)
{
fileSaveLocation = savetextBox.Text;
}
}
}
This is very easy to do with a single timer. The timer has a 1/10th second resolution (or so) and can be used directly to update the elapsed time. You can then use relative elapsed time within that timer to fire off your SNMP transaction, and you can reschedule the next one dynamically.
Here's a simple example
using System;
using System.Drawing;
using System.Windows.Forms;
class Form1 : Form
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
DateTime lastSnmpTime;
TimeSpan snmpTime = TimeSpan.FromSeconds(30);
DateTime startTime;
TextBox elapsedTimeTextBox;
Timer timer;
public Form1()
{
timer = new Timer { Enabled = false, Interval = 10 };
timer.Tick += new EventHandler(timer_Tick);
elapsedTimeTextBox = new TextBox { Location = new Point(10, 10), ReadOnly = true };
Controls.Add(elapsedTimeTextBox);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
startTime = DateTime.Now;
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
// Update elapsed time
elapsedTimeTextBox.Text = (DateTime.Now - startTime).ToString("g");
// Send SNMP
if (DateTime.Now - lastSnmpTime >= snmpTime)
{
lastSnmpTime = DateTime.Now;
// Do SNMP
// Adjust snmpTime as needed
}
}
}
Updated Q&A
With this code the timer fires once at the beginning where after I
press the stop button and call timer.Stop() and then press my start
button the timer doesn't fire until roughly 12 seconds later. Will
resetting the DateTimes fix this?
When the user presses the Start button, set lastSnmpTime = DateTime.MinValue. This causes the TimeSpan of (DateTime.Now - lastSnmpTime) to be over 2,000 years, so it will be greater than snmpTime and will fire immediately.
Also my output time in the text box looks like this: 0:00:02.620262.
Why is that? Is there a way to make it display only 0:00:02.62?
When you subtract two DateTime values, the result is a TimeSpan value. I used a standard TimeSpan formatting string of "g". You can use a custom TimeSpan formatting string of #"d\:hh\:mm\:ss\.ff" to get days:hours:minutes:seconds.fraction (2 decimal places).
Also will the timer go on and print out to the text box when it is run
for over 9 hours? Because I plan to have this running for 24 hrs+
If you use the custom format with 'd' to show the number of days, it will run for TimeSpan.MaxValue which is slightly more than 10,675,199 days, which is more than 29,000 years.
Below is my current code:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public int[] trialArray = new int[10];
public int trialCounter = -1;
private void button1_Click(object sender, EventArgs e)
{
bool button1Click = true;
if (button1Click == true)
{
ITIpanel.Visible = true;
for (int i = 0; i < trialArray.Length; i++) { trialArray[i] = -1; } // Set default value through array
int counter = 0;
Random rnd = new Random();
while (counter < 10 / 2)
{ // Red trials, fill half array
int index = rnd.Next(0, 10 - 1);
if (trialArray[index] == -1) { trialArray[index] = 1; ++counter; } //if unchanged value, change it
}
while (counter < 10)
{
int index = rnd.Next(0, 10);
if (trialArray[index] == -1) { trialArray[index] = 2; ++counter; }
}
}
}
private void ITIpanel_Paint(object sender, PaintEventArgs e)
{
if (ITIpanel.Visible == true)
{
trialCounter += 1;
timer1.Enabled = true;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
ITIpanel.Visible = false;
timer1.Enabled = false;
if (trialArray[trialCounter] == 1) { redstimPanel.Visible = true; }
else { bluestimPanel.Visible = true;}
if (trialCounter == 9) { Application.Exit(); }
}
public int counter = 0;
public event EventHandler Clicked5TimesEvent;
private void OnClicked5TimesEvent()
{ if (Clicked5TimesEvent != null) { Clicked5TimesEvent(this, EventArgs.Empty); } }
private void bluestimPanel_MouseDown(object sender, EventArgs e)
{
//FR requirement
counter++; if (counter % 5 == 0) { redstimPanel.Visible = false; ITIpanel.Visible = true; }
}
private void redstimPanel_MouseDown(object sender, EventArgs e)
{
//FR requirement
counter++; if (counter % 5 == 0) { redstimPanel.Visible = false; ITIpanel.Visible = true; }
}
}
}
As you can see, I am attempting to make a global array with 10 items. On the button click the 10 items are supposed to be altered such that half contain the value 1 and the other half contain the value 2.
Then, on the timer tick, depending on the value in the trialCounter, which determines the part of the array to be accessed, it should display either the redstimPanel or the bluestimPanel.
Therefore, if the 'trialCounter' is equal to 8, and 8 in the TrialArray is equal 1, the 'redstimPanel' should become Visible. Alternatively, if 8 in the 'TrialArray' is equal to 2, the 'bluestimPanel' should become Visible.
This, however, is not working as I would like it to. Thus, there are clearly some issues with my code. Do you all have any suggestions?
You never reset counter, or have the second loop (the one setting the 2s) be the full array.
There is also an error with the random number, rnd.Next(a,b) a - lower bound (inclusive), b - upper bound (exclusive). So it should be rnd.Next(0,10); so you have a chance of populating the last array position.
while (counter < 10 / 2) { // Red trials, fill half array
int index = rnd.Next(0, 10);
if (trialArray[index] == -1) { trialArray[index] = 1; ++counter; } //if unchanged value, change it
}
//Counter on the first loop here is already 5 (it exited the previous loop)
//So allow it to get to 10, and populate the FULL array.
while (counter < 10) {
int index = rnd.Next(0, 10);
if (trialArray[index] == -1) { trialArray[index] = 2; ++counter; }
}
Allow me to give you some tips and some explanations regarding your code:
First of all, you probably wanted that local button1Click variable to know later on whether the button has been clicked or not. For that to work, you should place it outside that function, otherwise it's never going to be used, and will be true with every button click, something like this:
bool button1Click = false;
private void button1_Click(object sender, EventArgs e)
{
if (!button1Click)
{
When you have a condition, you want the code to decide, whether an expression is true or false you may omit the part "== true" because it doesn't add anything new.
You have two whiles. Your idea was to run the counter until 5, with the first piece of code, and then from 5 to 10 the second piece of code. Now let me try to explain what is actually going on. The counter will go on until 5 filling 1s at random indices. Then at 5, the expression in the while will become false and it breaks out from the loop. Since the second while has the very same expression, it simply avoids it and goes on. One of the many solutions would be to have an if in the loop like this:
while (counter < 10)
{
if (counter<5)
{
// fill red
}
else
{
// fill blue
}
}
The way you fill up the values in your array. Have you thought about what's going to happen when the same index will be generated several times? It means it'll overwrite the previous value while certain index will remain -1.
This is the numeric changed event code with timer2 wich didnt solve hte problem the function im calling is DoThresholdCheck()
The problem is that in this function im creating each time im changing the numeric value a temp list each time im moving the numeric value change it the list is been created from the start. The problem is that if im using a big file in my program the list is containing sometimes 16500 indexs and its taking time to loop over the list so i guess when im changing the numeric value its taking time to loop over the list. If im using smaller video file for example the list containing 4000 indexs so there is no problems. I tried to use Timer2 maybe i could wait 0.5 seconds between each time the numeric value is changed but still dosent work good.
When im changing the numeric value while the program is running on a big video file its taking the values to be changed like 1-2 seconds ! thats a lot of time.
Any way to solve it ? Maybe somehow to read the list loop over the list faster even if the list is big ?
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
Options_DB.Set_numericUpDownValue(numericUpDown1.Value);
if (isNumericChanged == true)
{
isNumericChanged = false;
myTrackPanelss1.trackBar1.Scroll -= new EventHandler(trackBar1_Scroll);
DoThresholdCheck();
counter = 0;
}
}
private void timer2_Tick(object sender, EventArgs e)
{
counter++;
if (counter > 1)
{
isNumericChanged = true;
//timer2.Stop();
}
}
This is the DoThresholdChecks() function code:
private void DoThresholdCheck()
{
List<string> fts;
//const string D6 = "000{0}.bmp";
if (Directory.Exists(subDirectoryName))
{
if (!File.Exists(subDirectoryName + "\\" + averagesListTextFile + ".txt"))
{
return;
}
else
{
bool trackbarTrueFalse = false ;
fts = new List<string>();
int counter = 0;
double thershold = (double)numericUpDown1.Value;
double max_min_threshold = (thershold / 100) * (max - min) + min;
//label13.Text = max_min_threshold.ToString();
_fi = new DirectoryInfo(subDirectoryName).GetFiles("*.bmp");
for (int i = 0; i < myNumbers.Count; i++)
{
if (myNumbers[i] >= max_min_threshold)
{
//f.Add(i);
string t = i.ToString("D6") + ".bmp";
if (File.Exists(subDirectoryName + "\\" + t))
{
counter++;
button1.Enabled = false;
myTrackPanelss1.trackBar1.Enabled = true;
trackbarTrueFalse = true;
label9.Visible = true;
// myTrackPanelss1.trackBar1.Scroll += new EventHandler(trackBar1_Scroll);
//myTrackPanelss1.trackBar1.Minimum = 0;
// myTrackPanelss1.trackBar1.Maximum = f.Count;
// myTrackPanelss1.trackBar1.Value = f.Count;
// myFiles = new Bitmap(myTrackPanelss1.trackBar1.Value);
}
else
{
label9.Visible = false;
trackbarTrueFalse = false;
button1.Enabled = true;
myTrackPanelss1.trackBar1.Enabled = false;
myTrackPanelss1.trackBar1.Value = 0;
pictureBox1.Image = Properties.Resources.Weather_Michmoret;
label5.Visible = true;
secondPass = true;
break;
}
//fts.Add(string.Format(D6, myNumbers[i]));
}
}
//myTrackPanelss1.trackBar1.Maximum = _fi.Length - 1;
if (myTrackPanelss1.trackBar1.Maximum > 0)
{
if (trackbarTrueFalse == false)
{
myTrackPanelss1.trackBar1.Value = 0;
}
else
{
myTrackPanelss1.trackBar1.Maximum = counter;
myTrackPanelss1.trackBar1.Value = 0;
SetPicture(0);
myTrackPanelss1.trackBar1.Scroll += new EventHandler(trackBar1_Scroll);
}
//checkBox2.Enabled = true;
}
if (_fi.Length >= 0)
{
label15.Text = _fi.Length.ToString();
label15.Visible = true;
}
}
}
else
{
button1.Enabled = true;
}
}
try to cache results from DoThresholdCheck method
You can't magically get around the time the processing takes, if the processing is really necessary. You've got a couple of avenues to explore:
1) Minimise the processing being done - is all of it necessary? Can you cache any of it and only recompute a small amount each time the value changes?
2) Do the processing less often - do you have to recompute every single time?
3) Do the processing on another thread - then at least your UI remains responsive, and you can deliver the results to the UI thread when the background task is complete. However, this is going to be a relatively complicated variant of this pattern as you're going to need to be able to abort and restart if the value changes again while you're still processing the previous one.