计算挂起处理线程代码C#的待处理时间

时间:2015-01-15 20:14:42

标签: c# multithreading runtime

我有一个带线程的代码,我想显示完成处理的待处理时间。 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) );
        }
    }               

    }
}

1 个答案:

答案 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字节的倍数,否则您在计算总迭代次数时也会遇到错误。我也在上面解决了这个问题。