There is a functionality in my module, where the user can
scan the number of serial ports in the system and when the
user clicks "Auto scan" button, the code will have to go
through each serial port and send a test message and wait
for the reply.
I am using Progress bar control to show process of autoscan.
For which i need to pass the value to "x" and "Y" in my code to
update the bar. How can i pass the value since my code is already
in a foreach loop for getting the serialports.
Y = should pass the value of total number of serial ports
X = should iterate through each port and pass the value
Hope i am clear with req.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string strAckData = "";
foreach (SerialPort sp in comPortsList)
{
sp.Open();
string sendData = "Auto scan";
sp.Write(sendData);
strAckData += "Connection live on port " + sp.ReadExisting() + "\n";
sp.Close();
double dIndex = (double)x; **//How to pass the value here ?**
double dTotal = (double)y; **//How to pass the value here ?**
double dProgressPercentage = (dIndex / dTotal);
int iProgressPercentage = (int)(dProgressPercentage * 100);
// update the progress bar
backgroundWorker1.ReportProgress(iProgressPercentage);
}
richTextBox1.Invoke(new MethodInvoker(delegate { richTextBox1.Text = strAckData; }));
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ProgressBar.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
StatusLabel.Text = "Auto Scan completed";
}
You can get the number of ports from your comPortsList variable. Then the index is just a matter of incrementing a loop variable:
double dTotal = (double)(comPortsList.Count);
double dIndex = 0;
foreach (SerialPort sp in comPortsList)
{
// talk to serial port as at the moment
dIndex = dIndex + 1; // or ++dIndex to be more concise
double dProgressPercentage = dIndex / dTotal;
// etc.
}
Related
My programm (in C# using Windows Forms) is reading and parsing large amounts of Data and I'm using a Backgroundworker which calls those global methods (reading and parsing). I'd like to keep the user updated on how long it's going to take, so the Backgroundworker is supposed to display what action its doing and has a progressbar that should fill for every individual action too.
Unfortunately, I can't get it to work, as the progressbar just doesn't update at all and just stays empty.
Here is what I have so far:
private void InitializeBackgroundWorker()
{
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
}
private void buttonParse_Click(object sender, EventArgs e)
{
DescriptionLabel.Visible = true;
progressBar1.Visible = true;
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
Methods.ParsePerfusionData(backgroundWorker1); //Also tried using 'worker' here, but didnt work either
}
And in the method it looks like that:
public static void ParsePerfusionData(BackgroundWorker worker)
{
for (int i = 2; i < Globals.DataList.Count; i++)
{
worker.ReportProgress(i / amount * 100);
rest of the code etc.
}
}
Can I not use a backgroundworker in a global method like that? Thanks in advance!
When i < amount then i / amount * 100 = 0 * 100 = 0.
Simply use i * 100 / amount instead.
Also make sure backgroundWorker1.WorkerReportsProgress = true
You can only report progress between distinct operations. That means either:
using a very modern class that supports this level of reporting. Such a classs might not exist for your case.
reverse engineering parts of the code down to the loop you want to make reporting on. Usually the loop that itterates over files or the like.
GUI updates must be contained to RunWorkerCompelted and ProgressReport events. And depending on how often updates happen, ProgressReport may have to be kept to only updating a progress bar.
Here some old code I wrote with BackgroundWorker wich should get you started:
#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
if (!bgwPrim.IsBusy)
{
//Prepare ProgressBar and Textbox
int temp = (int)nudPrim.Value;
pgbPrim.Maximum = temp;
tbPrim.Text = "";
//Start processing
bgwPrim.RunWorkerAsync(temp);
}
}
private void btnPrimCancel_Click(object sender, EventArgs e)
{
if (bgwPrim.IsBusy)
{
bgwPrim.CancelAsync();
}
}
private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
int highestToCheck = (int)e.Argument;
//Get a reference to the BackgroundWorker running this code
//for Progress Updates and Cancelation checking
BackgroundWorker thisWorker = (BackgroundWorker)sender;
//Create the list that stores the results and is returned by DoWork
List<int> Primes = new List<int>();
//Check all uneven numbers between 1 and whatever the user choose as upper limit
for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
{
//Report progress
thisWorker.ReportProgress(PrimeCandidate);
bool isNoPrime = false;
//Check if the Cancelation was requested during the last loop
if (thisWorker.CancellationPending)
{
//Tell the Backgroundworker you are canceling and exit the for-loop
e.Cancel = true;
break;
}
//Determin if this is a Prime Number
for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
{
if (PrimeCandidate % j == 0)
isNoPrime = true;
}
if (!isNoPrime)
Primes.Add(PrimeCandidate);
}
//Tell the progress bar you are finished
thisWorker.ReportProgress(highestToCheck);
//Save Return Value
e.Result = Primes.ToArray();
}
private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pgbPrim.Value = e.ProgressPercentage;
}
private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
pgbPrim.Value = pgbPrim.Maximum;
this.Refresh();
if (!e.Cancelled && e.Error == null)
{
//Show the Result
int[] Primes = (int[])e.Result;
StringBuilder sbOutput = new StringBuilder();
foreach (int Prim in Primes)
{
sbOutput.Append(Prim.ToString() + Environment.NewLine);
}
tbPrim.Text = sbOutput.ToString();
}
else
{
tbPrim.Text = "Operation canceled by user or Exception";
}
}
#endregion
i have develop application for getting weight from weigh Bridge machine using C#.Net. i am trying lot of ways but, doesn't read correct data format weight from weigh bridge machine. i am getting output like
00000001Kg00000001B00000001B00000001B00000001B00000001B00000001B00000001B
continuously get from serial port.i want to get weight from weigh bridge machine my code is listed below:
private void Form1_Load(object sender, EventArgs e)
{
string[] portNames = SerialPort.GetPortNames();
foreach (var portName in portNames)
{
comboBox1.Items.Add(portName);
}
comboBox1.SelectedIndex = 0;
}
private void button1_Click(object sender, EventArgs e)
{
if (_serialPort != null && _serialPort.IsOpen)
_serialPort.Close();
if (_serialPort != null)
_serialPort.Dispose();
_serialPort = new SerialPort(comboBox1.Text, BaudRate, Parity.None, 8, StopBits.One);
_serialPort.DataReceived += SerialPortOnDataReceived;
_serialPort.Open();
textBox1.Text = "Listening on " + _serialPort.PortName + "...\r\n";
}
private delegate void Closure();
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
if (InvokeRequired)
BeginInvoke(new Closure(() => { SerialPortOnDataReceived(sender, serialDataReceivedEventArgs); }));
else
{
int dataLength = _serialPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);
if (nbrDataRead == 0)
return;
string str = System.Text.Encoding.UTF8.GetString(data);
textBox1.Text += str.ToString();
}
}
how could i get right weight for save it into my database? in Order to get the right weight it must be like
00000001Kg
at real time and change itself according to weigh scale weight.
Your last line of code is just appending everything to the textbox. You might want to clear it beforehand, and maybe try to check if the data you received is your undesired string (00000001B) and just don't add it.
To log data, you could use the TextChanged event of the textbox... just an idea...
I would like to perform the following action in C#:
Read the amount of lines in a specific text file.
Depending on the amount of lines in a text file, read each line and update the progress bar.
This is what I have so far:
private void Form1_Load(object sender, System.EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
int lineCount = 0;
int max = 100;
float percent;
using (var reader = File.OpenText(#"C:\file.txt"))
{
toolStripLabel1.Text = "Initializing...";
while (reader.ReadLine() != null)
{
lineCount++;
}
reader.Close();
for (int i = 0; i < lineCount; i++)
{
percent = (max / lineCount);
toolStripLabel1.Text = i.ToString() + " - " + percent + "%";
bw.ReportProgress(Convert.ToInt32(percent));
percent = percent + percent;
// Thread.Sleep(100);
}
}
}
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
// progressBar1.Value = (int)(((decimal)currentPosition / (decimal)length) * (decimal)100);
this.Text = e.ProgressPercentage.ToString();
}
Anyone have an idea on how to properly calculate and display the progress bar depending on what line is being read from the file?
Thanks in advance!
There are several problems with your code:
You're first reading the file, then after it has all been read you start updating the progress bar, which doesn't really make any sense.
You're doing integer division in your percentage calculation.
The percentage calculation isn't quite right.
You're updating the ToolStripLabel from the worker thread.
Try this:
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
var files = File.ReadAllLines( #"C:\file.txt" );
for( int i = 0; i < files.Length; i++ )
{
var line = files[i];
// do work on the current line here
int percentage = (int)( ( i / (double)files.Length ) * 100.0 );
bw.ReportProgress( percentage );
}
}
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
toolStripLabel1.Text = e.ProgressPercentage.ToString() + "%";
this.Text = e.ProgressPercentage.ToString();
}
If the file is very large and it's the actual reading that takes time, you should go back to your original way of reading it, but update the progress for every line instead of after. Though then you're back to the issue of not knowing how many lines there are before you have read the file. In that case - you could estimate the progress based on how many bytes/chars you have read compared to the full size of the file, which you can get without reading it all.
There are a few things you need to do
try this : replace
percent = (max / lineCount);
with this
percent = (100.0 * i / lineCount);
and remove percent = percent + percent;
Try this:
private void InvokeLabel(string text)
{
if (toolStripLabel1.InvokeRequired)
{
toolStripLabel1.Invoke(new Action<string>(InvokeLabel), text);
}
else
{
toolStripLabel1.Text = text;
}
}
For your progress bar it's the same code
I have created a program that uploads a file in server using ftp. Now I want to use a progress bar when file uploading in server. Means when file is upload progress bar start with value=0 when upload doing his work value of progress bar increase and when upload done value be max and then return to default;
i have no problem with upload just i dont know how to use progress bar when i uploading a file in server.
please help me.
my program picture
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
backgroundWorker1.RunWorkerAsync();
Upload(#openFileDialog1.FileName);
}
else
{ }
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(2);
backgroundWorker1.ReportProgress(i);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
this.Text = e.ProgressPercentage.ToString();
}
Here is an example of a program I use that processes a dynamic amount of parts and reports the progress. Hope it helps!
Here is the end of my part processing method:
int Progress = Convert.ToInt16(((Convert.ToDecimal(intCounter) / Convert.ToDecimal(txtPartsList.Lines.Count()))) * 100);
bw.ReportProgress(intCounter);
and the code for my progress changed handle:
private void bwExecuteProcess_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
int Progress = Convert.ToInt16(Math.Floor(((Convert.ToDecimal(e.ProgressPercentage) / Convert.ToDecimal(txtPartsList.Lines.Count()))) * 100));
lblTotal.Text = string.Format("Total Processed: {0} of {1}", e.ProgressPercentage, txtPartsList.Lines.Count());
lblReaderTime.Text = string.Format("Time Elapsed (sec): {0}", (swMainProcess.ElapsedMilliseconds / 1000));
pgsMain.Value = Progress;
lblPercentComplete.Text = string.Format("Percent Complete: {0}%", Progress);
ttpMain.SetToolTip(pgsMain, string.Format("{0}% Complete", Progress));
}
This is the code of the DoWork event the ProgressChanged event and the RunWorkerCompleted event. The problem is that the progressBar is getting to 100% much faster before the function process operation is end. So when the progressBar is up to 100% I'm getting error exception since the progressBar can't be 101%
I need somehow to make that the progressBar will get progress according to the function process / progress. I guess that something is wrong with my calculation in the DoWork event.
In the Form1 top I added:
Int i;
In the constructor I did:
i = 0;
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.RunWorkerAsync();
And this is the events of the Backgroundworker:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
//int currentLength;
//int currentIndex;
//int lastIndex = 0;
string startTag = "T256=\"";
string endTag = "\"";
int startTagWidth = startTag.Length;
//int endTagWidth = endTag.Length;
int index = 0;
h = new StreamReader(#"d:\DeponiaSplit\testingdeponias_Translated.txt");
while ((line = h.ReadLine()) != null)
{
if (index > f.LastIndexOf(startTag))
{
break;
}
int startTagIndex = f.IndexOf(startTag, index);
int stringIndex = startTagIndex + startTagWidth;
index = stringIndex;
int endTagIndex = f.IndexOf(endTag, index);
int stringLength = endTagIndex - stringIndex;
if (stringLength != 0)
{
string test = f.Substring(stringIndex, stringLength);
f = f.Substring(0, stringIndex) + line + f.Substring(stringIndex + stringLength);
if (listBox1.InvokeRequired)
{
textBox1.Invoke(new MethodInvoker(delegate { textBox1.Text = line; }));
}
i = i + 1;
System.Threading.Thread.Sleep(500);
worker.ReportProgress((i * 1));
}
}
h.Close();
StreamWriter w = new StreamWriter(#"D:\New folder (24)\000004aa.xml");
w.AutoFlush = true;
w.Write(f);
w.Close();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//this.progressBar1.Text = (e.ProgressPercentage.ToString() + "%");
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if ((e.Cancelled == true))
{
this.progressBar1.Text = "Canceled!";
}
else if (!(e.Error == null))
{
this.progressBar1.Text = ("Error: " + e.Error.Message);
}
else
{
this.progressBar1.Text = "Done!";
}
}
Why doesn't it work correctly?
Working using FileStream
Now I wanted to add to the progressBar a label which will show % and the label will move according to the progressBar I don't want to disable the progressBar green color progress just to add % and show the numbers in percentages.
So in the ProgressChanged event I did :
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
label3.Text = (e.ProgressPercentage.ToString() + "%");
}
But it doesn't work - the label13 doesn't move only the % changed to 1. I want to see something like 1%...2%...3%... and so on. How can I do it?
Why don't you use File.ReadAllLines, it returns an array of strings. You could report your progress as the percentage of the line you are processing to the total number of lines:
string[] lines = File.ReadAllLines(#"d:\DeponiaSplit\testingdeponias_Translated.txt");
// ...
worker.ReportProgress(i * 100 / lines.Length);
The "ReportProgress()" method is reporting "i" right after "i" has been incremented with the "i+1" statment. i is a variable that is incremented every time you have found a string that has matched your provided parameters. I think the problem here is that you are reporting an integer without context. Do you know how many lines total in the file contain a string that matches your parameters. I would suggest reporting (i/totalNumLinesMatchingParameters) * 100. This would report a number in terms of percentage. However, this does not include the action of writing the File. So you may want to scale the above differently if you intend to include the action of writing the File in your progress bar/progress bar label...