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;
Related
I made a C# WinForms application where I plot thousands of real time data points by using charts. I have noticed that during my application is running when I turn on lets say a web-browser the plot freezes. I tried to plot less points but it seems one never knows which program in parallel will be executed so I'm afraid the CPU usage of other programs depending on the PC will effect the performance.
edit:
private void button1_Click(object sender, EventArgs e)
{
///
_cts = new CancellationTokenSource();
_infiniteLoop = InfiniteLoop(_cts.Token);
}
private async Task InfiniteLoop(CancellationToken cancellationToken = default)
{
ushort[] ushortArray = null;
while (true)
{
Task loopMinimumDurationTask = Task.Delay(100, cancellationToken);
Task<ushort []> calculationTask = Task.Run(() => Calculate());
if (ushortArray != null) PlotData(ushortArray);
ushortArray = await calculationTask;
await loopMinimumDurationTask;
}
}
public ushort [] Calculate()
{
init();
daq.ALoadQueue(chArray, chRange, CHANCOUNT);
ScanOptions options = ScanOptions.Background | ScanOptions.Continuous | ScanOptions.ConvertData;
//setup the acquisiton
UL = daq.AInScan(FIRSTCHANNEL, SINGLE_KANAL_NUM, BUFFERSIZE, ref Rate, Range.Bip10Volts, buffer, options);
UL = daq.GetStatus(out daqStatus, out Count, out Index, FunctionType.AiFunction);
if ((Index >= HALFBUFFSIZE) & ReadLower) //check for 50% more data
{
//get lower half of buffer
UL = MccService.WinBufToArray(buffer, ushortArray, 0, HALFBUFFSIZE);
ReadLower = false; //flag that controls the next read
return ushortArray;
}
else if ((Index < HALFBUFFSIZE) & !ReadLower)
{
//get the upper half
UL = MccService.WinBufToArray(buffer, ushortArray, HALFBUFFSIZE, HALFBUFFSIZE);
ReadLower = true;//flag that controls the next read
return ushortArray;
}
return null;
}
public void PlotData(ushort[] datArray_Plot)
{
////////Thread.Sleep(10);
SerialList1.Clear();
for (int b = 0; b < HALFBUFFSIZE; b++)
{
UL = (daq.ToEngUnits(Range.Bip10Volts, datArray_Plot[b], out temp2));
SerialList1.Add(temp2);
SerialList2.Add(temp2);
ikb_p = ikb_p + 1;
}
int out_size = SerialList1.Count / h; //size of downsampled array
if (out_size <= 2)
out_size = 2;
array = SerialList1.ToArray(); //original array
if (h != 1)
array = Downsample(array, out_size); //downsampled array
if (ikb_p > BUFFERSIZE)
{
chart1.Series["Ch0"].Points.SuspendUpdates();
for (int b = 0; b < out_size; b++)
{
chart1.Series["Ch0"].Points.AddY(array[b]); //Plots each sample or use chart1.Series["Ch0"].Points.DataBindY(array);
if (chart1.Series["Ch0"].Points.Count > display_seconds * FREQ / h)
{
chart1.Series["Ch0"].Points.RemoveAt(0);
}
}
//chart1.Series["Ch0"].Points.ResumeUpdates();
chart1.Invalidate();
}
//FFT
if (SerialList2.Count > 4 * HALFBUFFSIZE / CHANCOUNT)
{
chart2.Series["Freq"].Points.Clear();
float sampling_freq = (float)FREQ;
float[] data = SerialList2.ToArray();
double[] dftIn = new double[data.Length];
double[] dftInIm = new double[data.Length];
double[] DftIn = new double[data.Length];
double[] FFTResult = new double[data.Length];
double[] f = new double[data.Length];
double[] power = new double[data.Length];
double[] window = MathNet.Numerics.Window.Hamming(data.Length);
for (int i = 0; i < data.Length; i++)
{
dftIn[i] = window[i] * (double)data[i];
}
for (int i = 0; i < data.Length; i++)
{
dftInIm[i] = 0.0;
}
FFT(dftIn, dftInIm, out reFFT, out imFFT, (int)Math.Log(data.Length, 2));
for (int i = 0; i < data.Length / 2; i++)
{
if (i > 0)
{
float a = sampling_freq / (float)data.Length;
float x = (float)i * a;
double y = Math.Sqrt(reFFT[i] * reFFT[i] + imFFT[i] * imFFT[i]);
f[i] = x;
FFTResult[i] = 2 * y / (data.Length / 2);
power[i] = 0.5 * FFTResult[i] * FFTResult[i];
}
}
double scale = data.Length / sampling_freq;
chart2.Series["Freq"].Points.DataBindXY(f, power);
float stdCh0 = 0;
float avg1 = SerialList2.Average();
float max1 = SerialList2.Max();
float min1 = SerialList2.Min();
float sum1 = (float)SerialList2.Sum(d => Math.Pow(d - avg1, 2));
stdCh0 = (float)Math.Sqrt((sum1) / (SerialList2.Count() - 1));
label5.Text = avg1.ToString("0.000000");
label22.Text = stdCh0.ToString("0.000000");
label70.Text = max1.ToString("0.000000");
label61.Text = min1.ToString("0.000000");
SerialList2.Clear();
label1.Text = count_sample.ToString();
}
///progressBar1
double ratio = (double)count_sample / (seconds * FREQ);
if (ratio > 1.000)
ratio = 1;
progressBar1.Value = (Convert.ToInt32(1000 * ratio));
progressBar1.Invalidate();
progressBar1.Update();
//Display event handlers
if (comboBox2_changed == true)
{
if (comboBox2.SelectedIndex == 0)
{
//chart1.ChartAreas[0].RecalculateAxesScale();
chart1.ChartAreas[0].AxisY.IsStartedFromZero = false;
}
if (comboBox2.SelectedIndex == 1)
{
//chart1.ChartAreas[0].RecalculateAxesScale();
chart1.ChartAreas[0].AxisY.IsStartedFromZero = true;
}
comboBox2_changed = false;
}
if (comboBox1_changed == true)
{
if (comboBox1.SelectedIndex == 0)
{
chart1.Series["Ch0"].ChartType = SeriesChartType.FastLine;
}
else
chart1.Series["Ch0"].ChartType = SeriesChartType.FastPoint;
}
if (num_updown1_changed)
{
display_seconds = (float)numericUpDown1.Value * 0.001f;
h = (int)numericUpDown2.Value;
chart1.Series["Ch0"].Points.Clear();
//chart1.ChartAreas[0].AxisX.Maximum = display_seconds * FREQ / h;
num_updown1_changed = false;
int avg = (int)((double)FREQ * (Decimal.ToDouble(numericUpDown1.Value) / 1000.0) / max_chart_points);
if (avg != 0)
numericUpDown2.Value = avg;
}
if (num_updown2_changed)
{
display_seconds = (float)numericUpDown1.Value * 0.001f;
h = (int)numericUpDown2.Value;
chart1.Series["Ch0"].Points.Clear();
//chart1.ChartAreas[0].AxisX.Maximum = display_seconds * FREQ / h;
num_updown2_changed = false;
}
}
private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
_cts.Cancel();
// Wait the completion of the loop before closing the form
try { _infiniteLoop.GetAwaiter().GetResult(); }
catch (OperationCanceledException) { } // Ignore this error
}
You could use threadpriority:
Thread.CurrentThread.Priority = ThreadPriority.Highest;
This is however considered to be poor form in most cases since the operating system is in a better position to decide what program deserves CPU time. And it does not need to follow your request for more time, even if you explicitly ask for it.
If plotting takes a considerable amount of time you might consider:
Can you optimize the plotting somehow?
Can you reduce the number of points?
you could perhaps plot a smaller part of the dataset?
You could pre-process the plot to reduce the point density. Screens typically have a resolution of 2k-4k, so if you have a line-chart with more points the user will not be able to see it anyway.
My suggestion is to scrap the obsolete BackgroundWorker, in favor of an infinite asynchronous loop. The example below assumes the existence of a Calculate method that should run on a background thread and should return the result of one calculation, and an UpdateUI method that should run on the UI thread and should consume this result.
private async Task InfiniteLoop(CancellationToken cancellationToken = default)
{
object calculationResult = null;
while (true)
{
Task loopMinimumDurationTask = Task.Delay(100, cancellationToken);
Task<object> calculationTask = Task.Run(() => Calculate());
if (calculationResult != null) UpdateUI(calculationResult);
calculationResult = await calculationTask;
await loopMinimumDurationTask;
}
}
This design has the following characteristics:
The Calculate and the UpdateUI methods are working in parallel.
If the Calculate completes first, it waits the completion of the UpdateUI before starting the next calculation.
If the UpdateUI completes first, it waits the completion of the Calculate before starting the next update of the UI.
If both the Calculate and the UpdateUI complete in under 100 milliseconds, an extra asynchronous delay is imposed, so that no more than 10 loops per second can occur.
The infinite loop can be terminated by canceling the optional CancellationToken.
The object type for the calculationResult variable in the above example is just for demonstration. Unless the result of the calculation is trivial, you should create a class or struct that can store all the data required for updating the UI on every loop. By eliminating all global state you minimize the number of things that can go wrong.
Usage example:
private CancellationTokenSource _cts;
private Task _infiniteLoop;
private void Form_Load(object sender, EventArgs e)
{
_cts = new CancellationTokenSource();
_infiniteLoop = InfiniteLoop(_cts.Token);
}
private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
_cts.Cancel();
// Wait the completion of the loop before closing the form
try { _infiniteLoop.GetAwaiter().GetResult(); }
catch (OperationCanceledException) { } // Ignore this error
}
in the following image generated by my code,
I want the tooltip to show value for each colour whilst my cursor is on it and when I click a particular place on the image i want a dash line to appear on the image.
this is my code:
RefBar.MouseMove += new MouseEventHandler(RefBar_MouseMove);
RefBar.MouseClick += new MouseEventHandler(RefBar_Click);
private void RefBar_MouseMove(object sender, MouseEventArgs e)
{
if (gotMapFirstTime == true)
{
Point LocalMousePosition = RefBar.PointToClient(System.Windows.Forms.Cursor.Position);
MousePointDisplay.SetToolTip(RefBar, WaferMap.getParamValueFromMousePointerXY(LocalMousePosition.X, LocalMousePosition.Y, 1, true).ToString());
}
}
private void RefBar_Click(object sender, EventArgs e)
{
byte[] bytes2;
Image image;
MouseEventArgs me = (MouseEventArgs)e;
Point coordinates = me.Location;
WaferMap.RefBarDashLines.Add(coordinates.Y);
int[] rfd = WaferMap.RefBarDashLines.ToArray();
if (rfd.Length > 2)
{
RefBar.Image.Dispose();
bytes2 = WaferMap.CreateMapReferenceBar(40, 580, 0, 0, 1);
WaferMap.RefBarDashLines = new List<int>();
WaferMap.UpperTrackBarLimit = 0.0;
WaferMap.LowerTrackBarLimit = 0.0;
pictureBox2.Image.Dispose();
bytes2 = WaferMap.CreateGridImage(120, 120, 9, 9, 5);
image = Image.FromFile(WaferMapImage);
pictureBox2.Image = image;
}
else if(rfd.Length == 2)
{
RefBar.Image.Dispose();
bytes2 = WaferMap.CreateMapReferenceBarByClick(40, 580, 0, 0, 1);
pictureBox2.Image.Dispose();
bytes2 = WaferMap.CreateGridImageFilteredByTrackBar(120, 120, 9, 9, 5);
image = Image.FromFile(WaferMapImage);
pictureBox2.Image = image;
}
else
{
RefBar.Image.Dispose();
bytes2 = WaferMap.CreateMapReferenceBarByClick(40, 580, 0, 0, 1);
}
image = Image.FromFile(ReferenceBarImage);
RefBar.Image = image;
MapLowerLimit.Text = coordinates.X.ToString() + " " + coordinates.Y.ToString();
}
in class wafermap we have this:
public static double getParamValueFromMousePointerXY(int x, int y, int boxSize, bool isRefBarOrHistogram)
{
double returnVal = 0.0;
Point UL;
Point BR;
int cellX;
int invertY;
int cellY;
if (isRefBarOrHistogram)
{
invertY = -1*(y - RefBarLength);
return get_YCell_to_ParamValue(invertY, RefBarLength);
}
else
{
foreach (die dd in dieList)
{
cellX = dd.col;
cellY = dd.row;
UL = new Point(boxSize * (cellX + 2), boxSize * (cellY + 4));
BR = new Point((boxSize * (cellX + 2)) + boxSize, (boxSize * (cellY + 4)) + boxSize);
if ((UL.X < x && x <= BR.X) && (UL.Y < y && y <= BR.Y))
{
return dd.ParamValue;
}
}
}
return returnVal;
}
public struct die
{
public int row;
public int col;
public int site;
public string param;
public double ParamValue;
}
the code for the Mouse click event works if the tool tip function is commented off, however when the tooltip function is is invoked for the mouse move function the code doesnt detect or detects after multiple clicks the mouse click event, how do i rectify this?
Your problem is probably that the getParamValueFromMousePointerXY takes so long to execute that your UI thread is blocked from execution any other task, such as handling your clicks.
You can offload the work to a background task and marshal setting the tooltip back to the UI thread:
Task.Run(() => {
string paramValue = WaferMap.getParamValueFromMousePointerXY(LocalMousePosition.X, LocalMousePosition.Y, 1, true).ToString();
MethodInvoker setTooltip = delegate() {
MousePointDisplay.SetToolTip(RefBar, paramValue);
};
RefBar.Invoke(setTooltip);
});
What you basically are doing here is to execute getParamValueFromMousePointerXY in a background task, while you continue to execute SetToolTip in the UI thread.
The only caveat here is that you possibly run a lot of background tasks here that will be in a race condition to set the tool tip. You can prevent that by using a cancellation token. You define a variable for a CancellationTokenSource:
CancellationTokenSource tooltipSource = null;
You can use this cancellation token source to prevent old updates to the tooltip:
tooltipSource?.Cancel();
tooltipSource = new CancellationTokenSource();
Task tooltipTask = new Task((tokenObj) => {
string paramValue = WaferMap.getParamValueFromMousePointerXY(LocalMousePosition.X, LocalMousePosition.Y, 1, true).ToString();
((CancellationToken)tokenObj).ThrowIfCancellationRequested();
MethodInvoker setTooltip = delegate() {
MousePointDisplay.SetToolTip(RefBar, paramValue);
};
RefBar.Invoke(setTooltip);
}, tooltipSource.Token);
tooltipTask.Start();
With this you should reduce the number of updates to your tooltip.
Of course you can pass the CancellationToken to getParamValueFromMousePointerXY and cancel the task even earlier.
I want to mute my Audio for certain duration, let's say after 2 seconds from it's start till 4 seconds of it's play duration, that is for 2 seconds.
I want to do this for 50 different Audios with different start and stop times for Muting. Currently, I am using two System.Timer class's objects with interval of 1st being Start time and of second being stop time for Muting and I have 50 if clauses to check for the 50 Audios and set their start and stop timer accordingly like this:
//50 checks
AudioFileReader ar;
Timer start_timer = new Timer(),stop_timer=new Timer();
public Form1()
{
InitializeComponent();
ar = new AudioFileReader(#"D:\SampleDegradedSpeech.wav");
var a = new WaveOut();
a.Init(ar);
a.Play();
start_timer.Interval = //start time;
stop_timer.Interval = //stop time;
start_timer.Tick += t1_Tick;
start_timer.Start();
stop_timer.Tick+=t2_Tick;
stop_timer.Start();
}
private void t2_Tick(object sender, EventArgs e)
{
ar.Volume = 1;
stop_timer.Stop();
}
private void t1_Tick(object sender, EventArgs e)
{
ar.Volume = 0;
start_timer.Stop();
}
Is there any other/better way of doing it?
Any replacements for the two timers?
Something like ar.mute(start,stop)?
You can write your own implementation of an IWaveProvider that wraps your WaveSource to set the sample bytes to 0 in the Read method when the underlying stream reached that point in time. You stop changing the byte array when you reached the end of the mute period.
A simple implementation of this is this MutingReader:
private class MutingReader : IWaveProvider
{
private TimeSpan _start;
private TimeSpan _end;
private WaveStream _stream;
// constructor
public MutingReader(WaveStream stream, TimeSpan start, TimeSpan end)
{
_stream = stream;
_start = start;
_end = end;
}
// gets called each time the WaveOut needs more bytes
public int Read(byte[] array, int offset, int count)
{
Debug.WriteLine(_stream.CurrentTime);
var samples = _stream.Read(array, offset, count);
// if we are between our Start and End Time stamps
if (_stream.CurrentTime > _start &&
_stream.CurrentTime < _end)
{
// silence by only returning zeroes in the array
for (int i = 0; i < count; i++)
{
array[i + offset] = 0;
}
}
return samples;
}
#region IWaveProvider Members
public WaveFormat WaveFormat
{
get { return _stream.WaveFormat; }
}
#endregion
}
You can use above implementation as follows:
var wo = new NAudio.Wave.WaveOutEvent();
var reader = new MutingReader(
new WaveFileReader( #"v1.wav"),
new TimeSpan(0,0,2), // mute after 2 seconds
new TimeSpan(0,0,4)); // unmute after 4 seconds
wo.Init(reader);
wo.Play();
I'm trying to control a piece of test equipment and I need to get the sequencing correct of how I communicate with it.
First I call StartGettingTraceData(). Then some time in the future I call StopGettingTraceData() to attempt to end the GetTraceData() function instead of it re-launching itself. But that NEVER happens. In fact, I never get to the line DoneTraces.Set() so on the line bool timedOut = !DoneTraces.WaitOne(10000), timedOut always is true;
private static AutoResetEvent DoneTraces = new AutoResetEvent(false);
private void GetTraceData()
{
byte[] receivedbytes = new byte[1];
if (Connection.ReadData(receivedbytes) && receivedbytes[0] == 192)
ProcessIncomingTrace();
Thread.Sleep(100);
if (RunTraceQueryWorker)
new Thread(GetTraceData).Start();
else
{
Thread.Sleep(200);
DoneTraces.Set();
}
}
private void StartGettingTraceData()
{
RunTraceQueryWorker = true;
new Thread(GetTraceData).Start();
}
private bool StopGettingTraceData()
{
RunTraceQueryWorker = false;
bool timedOut = !DoneTraces.WaitOne(10000);
return timedOut;
}
Any thoughts on what is going on?
EDIT:
Here is my Connection.ReadData(...) function. It's a serial connection by the way.
public bool ReadData(byte[] responseBytes)
{
int bytesExpected = responseBytes.Length, offset = 0, bytesRead;
while (bytesExpected > 0 && (bytesRead = MySerialPort.Read(responseBytes, offset, bytesExpected)) > 0)
{
offset += bytesRead;
bytesExpected -= bytesRead;
}
return bytesExpected == 0;
}
Rather than recusively calling GetTraceData again, you should use a while loop looking at your condition like this:
private static AutoResetEvent DoneTraces = new AutoResetEvent(false);
private void GetTraceData()
{
do
{
byte[] receivedbytes = new byte[1];
if (Connection.ReadData(receivedbytes) && receivedbytes[0] == 192)
ProcessIncomingTrace();
Thread.Sleep(100);
}
while (RunTraceQueryWorker)
Thread.Sleep(200);
DoneTraces.Set();
}
private void StartGettingTraceData()
{
RunTraceQueryWorker = true;
new Thread(GetTraceData).Start();
}
private bool StopGettingTraceData()
{
RunTraceQueryWorker = false;
bool timedOut = !DoneTraces.WaitOne(10000);
return timedOut;
}
It's impossible to know specifically why your code is freezing without understanding what ReadData & ProcessIncomingTrace() do.
Well, chances are that the ReadData call is blocking. As an aside, you're making it hard on yourself with all this recursive threading... Can't you just use a loop?
private void GetTraceData()
{
byte[] receivedbytes = new byte[1];
while( RunTraceQueryWorker )
{
if( Connection.ReadData(receivedbytes) && receivedbytes[0] == 192 )
{
ProcessIncomingTrace();
}
Sleep(100);
}
Thread.Sleep(200);
DoneTraces.Set();
}
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.