I want to calculate download speed as kbps (kb per second). There's a problem in the code, it doesn't show actual speed. And I'm really tired of this work. Also, when using (TotalDownloadSize / ElapsedTime) formula it shows more realistic results but you know it will get average value and it will be stupidity.
It usually gives 4000 and it's basicly because of chunk 4096 when I set it to 128 that time I get 50/100/125 values.
DateTime dlElapsed;
private delegate void UpdateProgessCallback(Int64 BytesRead, Int64 TotalBytes, Int32 CurrentBytes);
private void UpdateProgress(Int64 BytesRead, Int64 TotalBytes, Int32 CurrentBytes)
{
DateTime Elapsed = DateTime.Now;
var progress = Convert.ToInt32((BytesRead * 100) / TotalBytes);
var elaps = (Elapsed - dlElapsed).TotalSeconds;
long kbps;
if (elaps > 0)
{
kbps = Convert.ToInt64((CurrentBytes / elaps) / 1024);
updateLabelText(String.Format("Downloading ({0} kbps)...", kbps));
}
// Make progress on the progress bar
if (progress < progressBar1.Maximum)
{
progressBar1.Value = progress;
}
else
{
progressBar1.Value = progressBar1.Maximum;
}
dlElapsed = DateTime.Now;
}
private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
// Some stuff here...
int byteSize = 0;
byte[] downBuffer = new byte[4096];
FileStream strLocal= new FileStream(path, FileMode.Create, FileAccess.Write);
dlElapsed = DateTime.Now;
while ((byteSize = stream.Read(downBuffer, 0, downBuffer.Length)) > 0)
{
strLocal.Write(downBuffer, 0, byteSize);
this.Invoke(new UpdateProgessCallback(this.UpdateProgress),
new object[] { strLocal.Length, totalbyte, byteSize});
}
updateLabelText("Download complete!");
strLocal.Close();
}
}
So where's the problem?
So where's the problem?
You're coarsely sampling something that varies a lot.
Consider buffering measurements and averaging the last 5 or so. Look for implementations of a "running average".
Well, my first comment would be that your code is not thread safe, so when you set dlElapsed = DateTime.Now;, it's not the same dlElapsed value that UpdateProgress is going to be checking.
Related
I have two voids that have to be called after one another every 5 seconds.I mean first the first void has to be called and after that the second void has to be called and the we have 5 seconds break...but my program only calls the first void(get pressure) and ignores the second one....could anyone show me the code?
private void getPressure()
{
if (serialPort1.IsOpen)
{
string PCR = "";
byte[] readCommand = { 0x50, 0x0D };
serialPort1.Write(readCommand, 0, 2);
int bytestoread = serialPort1.BytesToRead;
if (bytestoread > 0)
{
byte[] input = new byte[bytestoread];
serialPort1.Read(input, 0, bytestoread);
PCR = System.Text.Encoding.UTF8.GetString(input);
}
if (PCR.StartsWith("P"))
{
if (PCR.Length > 15)
{
PCR = PCR.Substring(3, PCR.IndexOf("T") - 3).Trim();
var decPCR = Decimal.Parse(PCR, NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint);
rTxtBoxPressure.Text = decPCR + " Torr";
double data;
bool result = Double.TryParse(decPCR.ToString(), out data);
if (result)
{
serialDataChart.TriggeredUpdate(data);
}
}
}
}
}
private void getVoltage()
{
if (serialPort1.IsOpen)
{
string UCR = "";
byte[] readCommand2 = { 0x55, 0x0D };
serialPort1.Write(readCommand2, 0, 2);
int bytestoread2 = serialPort1.BytesToRead;
if (bytestoread2 > 0)
{
byte[] input2 = new byte[bytestoread2];
serialPort1.Read(input2, 0, bytestoread2);
UCR = System.Text.Encoding.UTF8.GetString(input2);
}
if (UCR.StartsWith("V"))
{
if (UCR.Length > 15)
{
UCR = UCR.Substring(5, UCR.IndexOf("Volts") - 5).Trim();
var decUCR = Decimal.Parse(UCR, NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint);
rtxtBoxVoltage.Text = decUCR + " Volts";
double data;
bool result = Double.TryParse(decUCR.ToString(), out data);
if (result)
{
serialDataChart2.TriggeredUpdate(data);
}
}
}
}
}
private void InitTimer()
{
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval =5000;
timer1.Start();
}
private void timer1_Tick(object sender , EventArgs e)
{
getPressure();
getVoltage();
}
First of all, you define your time with Interval = 5000, which will trigger timer event every 5 seconds.
Secondly, in timer event handler you call desired methods one after another, without any interval, so once getPressure finishes, getVoltage starts immediately.
So, to sum it up - you don't need timer, as in your requirements I don't see that both functions should be called periodically. The only thing we need to call one, and then after 2 seconds call another, so I'd suggest something among the lines
getPressure();
// wait two seconds between calls, you could also use Thread.Sleep(2 * 1000)
await Task.Delay(2 * 1000);
getVoltage();
IF you want to wait 2 seconds before calling getVoltage, but it should be 2 seconds from starting getPressure, then the code should look like:
var pressureTask = Task.Run(() => getPressure());
await Task.Delay(2 * 1000);
getVoltage();
await pressureTask;
I am trying to read real time data from an accelerometer. Sampling frequency of the accelerometer is 2650Hz. I am getting proper data from serial port, but unable to match with the sampling frequency. The sampling frequency is varying from 2100Hz to 2400Hz and it is not stable. I am using a stop watch for timing reference.
Here is my code for receiving serial data.
private void toolStripButton12_Click(object sender, EventArgs e)
{
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(115200);
if (!serialPort1.IsOpen)
{
serialPort1.Open();
}
sw.Start();
serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(SerialPort1_DataReceived);
}
}
private void SerialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
{
byteCount = serialPort1.BytesToRead;
if (byteCount > 4000)
byteCount = 4000;
if (e.EventType == SerialData.Eof)
return;
byte[] buffer = new byte[byteCount];
int readBytes = serialPort1.Read(buffer, 0, buffer.Length);
// FIFO Implementation
buffer.ToList().ForEach(b => newrecievedData1.Enqueue(b));
if (newrecievedData1.Count < 4000) return;
processdata3();
int i = 0;
{
while (i <= packet3.Length-4)
{
while (packet3[i++] != 69) ;
data = packet3[i++];
a = data << 8;
b = a + packet3[i++];
c = b << 8;
d = c + packet3[i++];
Port1data.Add(d);
countbyte[0]++;
tick = (double)countbyte[0];
}
}
t = (double)sw.Elapsed.TotalSeconds;
Sampling frequency = tick / t;
}
try
{
this.Invoke(new EventHandler(DisplayText));
}
catch
{
}
}
Int32[] packet3;
private Int32[] processdata3()
{
if (newrecievedData1.Count >= 4000)
{
packet3 = Enumerable.Range(0, 4000).Select(h => newrecievedData1.Dequeue()).ToArray();
}
return packet3;
}
I want to exactly get 2650 Hz sampling frequency all the time.Any help is highly appreciated.
That is 0.337 ms per sample. That is really pushing the upper limits of how much code can be done per sample.
Without some major optimization to your algorithms (possibly using custom collections designed specifically for your workload) I don't think your requirements are reachable using managed code.
I have dialer program in C#. I wanted to change image if download / upload is in progress. How can I add such check in following code?
private void UpdateNetworkInterface()
{
this.Invoke((MethodInvoker)delegate
{
NetworkInterface nic = nicArr[cmbInterface.SelectedIndex];
IPv4InterfaceStatistics interfaceStats = nic.GetIPv4Statistics();
long lngBytesSent = 0;
long lngBtyesReceived = 0;
int bytesSentSpeed = (int)(interfaceStats.BytesSent - lngBytesSent) /1024;
int bytesReceivedSpeed = (int)(interfaceStats.BytesReceived - lngBtyesReceived) /1024;
// Update the labels
lblInterfaceType.Text = nic.NetworkInterfaceType.ToString();
lblUpload.Text = bytesSentSpeed.ToString() + " KB";
lblDownload.Text = bytesReceivedSpeed.ToString() + " KB";
//this.StatusTextBox.AppendText(string.Format("{0}\r\n\r\n DOWNLOAD/UPLOAD in progress", ""));
});
}
Those property gives you the total bytes transferred, what you need is the derivative of that number (The rate of change).
The easiest way is just do the simple math problem
So you will need to recordings then compare those two points to get the speed.
private long _lastBytesRecevied;
private long _lastBytesSent;
private DateTime _lastReceivedMesurement;
private DateTime _lastSentMesurement;
//This needs to be done once at the start of the class to "seed" the first value.
private Init()
{
_lastReceivedMesurement = DateTime.UtcNow;
_lastBytesRecevied = interfaceStats.BytesReceived;
_lastSentMesurement = DateTime.UtcNow;
_lastBytesSent = interfaceStats.BytesSent;
}
private double getKBDownloadSpeed()
{
double result = (interfaceStats.BytesReceived - _lastBytesRecevied) / (DateTime.UtcNow - _lastReceivedMesurement).TotalSeconds;
_lastReceivedMesurement = DateTime.UtcNow;
_lastBytesRecevied = interfaceStats.BytesReceived;
return result / 1024d;
}
private double getKBUploadSpeed()
{
double result = (interfaceStats.BytesSent - _lastBytesSent) / (DateTime.UtcNow - _lastSentMesurement).TotalSeconds;
_lastSentMesurement = DateTime.UtcNow;
_lastBytesSent = interfaceStats.BytesSent;
return result / 1024d;
}
Now your two functions returns the average download speed between the last time the function was called and the current call.
If you get value in download speed, change the image as download icon.
If you get value in Upload speed, change the image as upload icon.
Sincerely,
Thiyagu Rajendran
**Please mark the replies as answers if they helps.
You can use System.Net.WebClient to do it.
it has an event DownloadProgressChanged and it has parameters and it has fields that contain downloaded bytes and total bytes of the file.
It is fired by WebClient.DownloadFileAsync().
MSDN Link : https://msdn.microsoft.com/en-us/library/system.net.webclient(v=vs.110).aspx
Example :
private void DownloadChanged(object sender, DownloadProgressChangedEventArgs e)
{
labelProgress.Text = string.Format("{0} Percents Completed",
e.BytesReceived / e.TotalBytesToReceive * 100);
}
private void StartDownload(object sender, EventArgs e) // Button Event
{
var webClient = new WebClient();
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadChanged);
webClient.DownloadFileAsync(/* URL */);
}
Getting upload bytes is same as Download one. Happy Programming! :)
I am writing a program which copies a file. I have the file copying correctly, the progress bar updates, but I get an error which states that the e.ProgressPercentage is at 101. The code for the bgWorker_ProgressChanged event handler is:
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// We will increase the progress bar when work progress is reported.
pbCopyProgress.Maximum = 100;
pbCopyProgress.Value = e.ProgressPercentage;
}
Here is the code for the bgWorker_DoWork event handler:
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Gets the size of the file in bytes.
Int64 iSize = strInputFile.Length;
// Keeps track of the total bytes downloaded so we can update the progress bar.
Int64 iRunningByteTotal = 0;
// Open the input file for reading.
using (FileStream InputFile = new FileStream(strInputFile, FileMode.Open, FileAccess.Read, FileShare.None))
{
// Using the FileStream object, we can write the output file.
using (FileStream OutputFile = new FileStream(strOutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
// Loop the stream and get the file into the byte buffer.
int iByteSize = 0;
byte[] byteBuffer = new byte[iSize];
while ((iByteSize = InputFile.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
{
// Calculate the progress out of a base "100."
double dIndex;
double dTotal;
double dProgressPercentage;
// Write the bytes to the file system at the file path specified.
dIndex = (double)(iRunningByteTotal);
dTotal = (double)byteBuffer.Length;
dProgressPercentage = (dIndex / dTotal);
OutputFile.Write(byteBuffer, 0, iByteSize);
iRunningByteTotal += iByteSize;
intProgress = Convert.ToUInt16(dProgressPercentage);
// Update the progress bar.
bgWorker.ReportProgress(intProgress);
}
// Close the output file.
OutputFile.Close();
}
// Close the input file.
InputFile.Close();
}
}
As I said, the progress bar is updating, but I get an error because it seems to continue copying the file after it has reached 100 percent. If I put in a MessageBox.Show(Convert.ToString(intProgress)) immediately after the bgWorker.ReportProgress(intProgress) line, the dialog will pop up with 101 for the text. Any help will be greatly appreciated.
You're dividing your running total by the length of the block buffer, not the whole stream, which means the result is basically unbounded. You're failing to multiply by 100 too, but that problem is masked by the fact that the ratio is growing larger than one.
But you're making it all look very difficult - the code you want is simply:
bgWorker.ReportProgress((int)(100 * runningByteTotal / fileLength))
You should set up fileLength before the start of the loop (and it needs to be the length of the file, not the filename, as #azyberezovsky points out in his answer).
You can allow this calculation to happen with simple integer arithmetic rather than needing floating point types, as long as the multiply by 100 happens before the divide.
As a stylistic point, you don't need all the 'i's and 'd's in front of variable names - that's not considered to be good C# style. Nor are variables normally started with a capital letter - if nothing else, that confuses the SO code syntax highlighter...
That is not size of file - it is simply length of file name string:
Int64 iSize = strInputFile.Length;
And this is also not file size, this is a size of buffer you use to write data to output file:
dTotal = (double)byteBuffer.Length;
What you need is
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
using (FileStream inputFile = new FileStream(strInputFile, FileMode.Open, FileAccess.Read, FileShare.None))
using (FileStream outputFile = new FileStream(strOutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
long totalBytesToWrite = inputFile.Length;
long totalBytesWritten = 0;
byte[] buffer = new byte[512]; // provide any buffer size here
int bytesToWrite;
ushort percentage;
while ((bytesToWrite = inputFile.Read(buffer, 0, buffer.Length)) > 0)
{
outputFile.Write(buffer, 0, bytesToWrite);
totalBytesWritten += bytesToWrite;
percentage = (ushort)((100 * totalBytesWritten)/totalBytesToWrite);
bgWorker.ReportProgress(percentage);
}
}
}
Keep in mind - you don't need to close stream manually if you are using using block - stream will be disposed (i.e. closed) at the end of this block.
Declare maximum value of:
pbCopyProgress.Maximum = InputFile.Read(byteBuffer, 0, byteBuffer.Length)
Remove line:
percentage = (ushort)((100 * totalBytesWritten)/totalBytesToWrite);
from bgWorker_DoWork, and declare counter before while cycle in bgWorker_DoWork. For example:
int counter = 1;
before the closing brace of while increment the counter (counter++);
in bgWorker_ProgressChanged update the percentage:
pbCopyProgress.Value = e.ProgressPercentage;
If you want to fill any label with text showing the percentage the following line calculates the percentage:
int percent = 100 / (byteBuffer.Length / e.ProgressPercentage);
Label1.Text = String.Format("Passed: {0} %, percent.ToString());
Those lines should be also in bgWorker_ProgressChanged.
I want to create a huge dummy file say 1~2 GBs in matter of seconds.
here is what I've written in C#:
file.writeallbytes("filename",new byte[a huge number]);
and another way with indicating the status, was like following:
long FSS = din.TotalFreeSpace;
long segments = FSS / 10000;
long last_seg = FSS % 10000;
BinaryWriter br = new BinaryWriter(fs);
for (long i = 0; i < segments; i++)
{
br.Write(new byte[10000]);
this.label2.Text = "segments write :" + i.ToString() + "\r\n" + "segments remain :" + ((segments-i)+1).ToString();
Application.DoEvents();
}
br.Write(new byte[last_seg]);
this.label2.Text += "\r\nDone!";
br.Close();
where din is Disk Information object
well with these two approach it takes something like 2 or more minutes to write such a big but dummy file. Is there any other faster way for doing so?
Simply create the file, seek to a suitably large offset, and write a single byte:
FileStream fs = new FileStream(#"c:\tmp\huge_dummy_file", FileMode.CreateNew);
fs.Seek(2048L * 1024 * 1024, SeekOrigin.Begin);
fs.WriteByte(0);
fs.Close();
This will yield a 2GB file with basically unpredictable contents, which should be fine for your purposes.
If you don't care about the contents, then by far the fastest way I know of is this - it is practically instant:
private void CreateDummyFile(string fileName, long length)
{
using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
fileStream.SetLength(length);
}
}
If you just need a FileStream, you could use FileStream.SetLength. That will get you a stream which is 2 GB long. Then you can write the final byte at an arbitrary position of your choice. But the contents will be undefined.
If you're trying to actually create a file on the disk, yes, you'll need to actually write its contents. And yes, hard disks are going to be slow; something like a 1 GB/min write speed isn't totally ridiculous. Sorry -- that's physics!
Why did you not use the BackgroundWorker class to achieve this, as you can pass anything into the method ReportProgress to indicate the status report. See the example below:
private BackgroundWorker bgWorker;
public Form1()
{
InitializeComponent();
bgWorker = new BackgroundWorker();
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
bgWorker.RunWorkerAsync();
}
void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.label2.Text = "Done";
}
void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
MyStatus myProgressStatus = (MyStatus)e.UserState;
this.label2.Text = string.Format("segments write : {0}" + Environment.Newline + "Segments Remain: {1}", myProgressStatus.iWritten, myProgressStatus.iRemaining);
}
void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
long FSS = din.TotalFreeSpace;
long segments = FSS / 10000;
long last_seg = FSS % 10000;
BinaryWriter br = new BinaryWriter(fs);
for (long i = 0; i < segments; i++)
{
br.Write(new byte[10000]);
bgWorker.ReportProgress(i.ToString(), new MyStatus(i, ((segments-i) + 1)));
}
br.Write(new byte[last_seg]);
br.Close();
}
public class MyStatus{
public int iWritten;
public int iRemaining;
public MyStatus(int iWrit, int iRem){
this.iWritten = iWrit;
this.iRemaining = iRem;
}
}
}
This is a rough draft...
I could be wrong but you will probably find that it's impossible to create a file that large that quickly as there will be a bottleneck in the I/O writing process.
However in your code above the Applciation.DoEvents will be slowing things down. Also any repainting of the screenthis.label2.Text = will cause a slight slow down.