我有一个带线程的代码,我想显示完成处理的待处理时间。 button1调用 功能"功能1()"在一个while循环中控制的1024字节块中读取文件,直到结束 的文件。在" While循环中#34;有一个" foreach循环"在哪里被称为" Function2()"。我开始吧 " while循环"开头的计时器并在#34; while循环"结束时停止它。在那之后我尝试了 计算aprox的待定时间首先知道将由" while循环"处理的迭代次数。 然后我保存第一次迭代的"经过的时间" (比方说T1)然后我将它乘以迭代次数。
这将是
PendingTime = T1*Iterations.
然后我做
PendingTime = PendingTime - Ti, where Ti is the ElapsedTime of the ith iteration.
问题是当我尝试使用真实代码时,T1 * Iterations的多重播放给了我402s 处理需要12秒。
也许有些专家可以看到我做错了什么。提前谢谢。
代码如下所示:
async void button1_Click(object sender, EventArgs e)
{
//Some code
await Task.Run(() => Function1(inputfile, cts.Token), cts.Token);
//Some code
}
public void Function2()
{
//Some code
}
public void Function1(string inputfile, CancellationToken token)
{
int buffer = 1024;
int IterationCounter = 0;
decimal Iterations = 1;
int PendingTime = 0;
using (BinaryReader reader = new BinaryReader(File.Open(inputfile, FileMode.Open)))
{
FileLength = (int)reader.BaseStream.Length;
Iterations = (int)FileLength/buffer;
while (chunk.Length > 0)
{
Stopwatch sw1 = Stopwatch.StartNew(); //Start time counter
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//some code
chunk = reader.ReadBytes(buffer);
foreach (byte data in chunk)
{
//Some code
Function2(); //Call to Function2
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Checking if it is the first iteration to save the pending time
//Pending time would be the elapsed time for the first iteration
//multiplied by the number of iterations (FileLength/1024).
sw1.Stop(); //Stop time counter
if (IterationCounter == 1)
{
PendingTime = (int)((decimal)Math.Round(sw1.Elapsed.TotalMilliseconds / 1000, 4)*Iterations);
}
//Show in TexBox1 the pending time
TextBox1.Invoke((MethodInvoker)delegate
{
PendingTime = PendingTime - (int)Math.Round(sw1.Elapsed.TotalMilliseconds / 1000, 4);
TextBox1.Text = PendingTime + " s";
});
}
}
}
更新
我根据Peter Duniho的例子使用以下代码进行测试。
可以使用任何文件(即txt文件)进行测试。我已经使用5MB的txt文件进行了测试,执行时间为3秒,但是在TextBox1中,待处理时间始终为零。我哪里错了?
注意:我改变了这个:
double timePerIteration = sw1.Elapsed / ++IterationCounter;
到这个
double timePerIteration = sw1.ElapsedMilliseconds/1000/ ++IterationCounter;
因为我收到错误:
Operator '/' cannot be applied to operands of type 'System.TimeSpan' and 'int' (CS0019)
到目前为止的代码是。谢谢你的帮助。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TestTimer
{
public partial class MainForm : Form
{
CancellationTokenSource cts = new CancellationTokenSource();
string filename = "";
long FileLength;
FileInfo fInfo;
Stopwatch sw1 = new Stopwatch();
public MainForm()
{
InitializeComponent();
}
void BtnSelectFileClick(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "Select file";
DialogResult dr = ofd.ShowDialog();
if (dr == DialogResult.OK)
{
filename = ofd.FileName;
fInfo = new FileInfo(filename);
}
else
{
MessageBox.Show("File not found");
return;
}
}
async void BtnRunProcessClick(object sender, System.EventArgs e)
{
cts = new CancellationTokenSource();
await Task.Run(() => Function1(filename, cts.Token), cts.Token);
}
public void Function1(string inputfile, CancellationToken token)
{
int buffer = 1024;
int IterationCounter = 0;
int Iterations = 0;
double pendingTime = 0;
using (BinaryReader reader = new BinaryReader(File.Open(inputfile, FileMode.Open)))
{
FileLength = (int)reader.BaseStream.Length;
Iterations = (int)FileLength/buffer;
byte[] chunk;
sw1 = Stopwatch.StartNew(); //Start time counter
while (true)
{
chunk = reader.ReadBytes(buffer);
if (chunk.Length == 0) {break;}
foreach (byte data in chunk)
{
Thread.Sleep(90/100);
}
// pendingTime is the current average time-per-iteration,
// times the number of iterations left
double timePerIteration = sw1.ElapsedMilliseconds/1000/ ++IterationCounter;
pendingTime = timePerIteration * (Iterations - IterationCounter);
TextBox1.Invoke((MethodInvoker)delegate
{
// Let string.Format() take care of rounding for you
TextBox1.Text = string.Format("{0:0} s", pendingTime / 1000);
});
}
MessageBox.Show("Execution time: " + string.Format("{0:0} s", sw1.ElapsedMilliseconds / 1000) );
}
}
}
}
答案 0 :(得分:1)
我看不到你发布的代码是如何实际编译的,从不介意工作。 FileLength
变量似乎没有被声明,并且您永远不会递增IterationCounter
变量,每次迭代都会给出一个负PendingTime
值。即使您增加了计数器,您的PendingTime
变量的实际含义也会从计数器为1
时执行的块更改,稍后当您从当前PendingTime
中减去经过的时间时变量
这表明您发布的代码实际上并不是您正在使用的代码,因为显示的剩余时间总是为负数(即使假设FileLength
的声明只是意外地从您的帖子中删除了一些原因)。为了论证,我将添加一个执行增量的语句......
正如评论家克里斯所说,当每次迭代的实际持续时间变化时,就像这里的情况一样,你要做的最好的事情就是将所有迭代的平均值都计算到当前值。即使这样也可能导致错误的剩余时间显示,从迭代到迭代的变化相当大(特别是如果迭代次数很少),但至少它更可能接近。
这样的事情对你来说可能会更好:
public void Function1(string inputfile, CancellationToken token)
{
int buffer = 1024;
int IterationCounter = 0;
int Iterations;
using (BinaryReader reader = new BinaryReader(File.Open(inputfile, FileMode.Open)))
{
if (reader.BaseStream.Length == 0)
{
// nothing to do
return;
}
// NOTE: this won't work for files with length > int.MaxValue!
// Your original code has the same limitation, and I have not
// bothered to change that.
// Now that we know for sure the length is > 0, we can
// do the following to ensure a correct iteration count
Iterations = ((int)reader.BaseStream.Length - 1) / buffer + 1;
Stopwatch sw1 = Stopwatch.StartNew();
while (chunk.Length > 0)
{
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//some code
chunk = reader.ReadBytes(buffer);
foreach (byte data in chunk)
{
//Some code
Function2(); //Call to Function2
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// pendingTime is the current average time-per-iteration,
// times the number of iterations left
double timePerIteration = sw1.ElapsedMilliseconds / ++IterationCounter,
pendingTime = timePerIteration *
(Iterations - IterationCounter);
//Show in TexBox1 the pending time
TextBox1.Invoke((MethodInvoker)delegate
{
// Let string.Format() take care of rounding for you
TextBox1.Text = string.Format("{0:0} s", pendingTime / 1000);
});
}
}
}
除非您保证输入文件的长度始终是1024字节的倍数,否则您在计算总迭代次数时也会遇到错误。我也在上面解决了这个问题。