为什么在下载图像时,progressBar永远不会达到100%并且我超出了范围异常?

时间:2016-12-29 06:42:05

标签: c# .net winforms

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Threading;

namespace SatelliteImages
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            ExtractImages ei = new ExtractImages();
            ei.Init();

            progressBar1.Minimum = 0;
            progressBar1.Maximum = 100;

            backgroundWorker1.RunWorkerAsync();
        }



        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {

        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            for (int i = 0; i <= ExtractImages.imagesUrls.Count(); i++)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    using (var client = new WebClient())
                    {
                        client.DownloadFile(ExtractImages.imagesUrls[i], @"C:\Temp\TestingSatelliteImagesDownload\" + i + ".jpg");
                        worker.ReportProgress(100 * i / ExtractImages.imagesUrls.Count());
                    }
                }
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            label2.Text = (e.ProgressPercentage.ToString() + "%");
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                MessageBox.Show("Completed without any errors");
            }
            else
            {
                string myerr = e.Error.ToString();
            }
        }
    }
}
  1. 为什么progressBar1达到99%并停在那里然后进入已完成的事件?我怎样才能达到100%?

  2. 我计算reportProgress的方式和从i = 0开始的FOR循环是否正常?

  3. 如何在表单上显示一个新标签,例如label3,并显示要下载的文件数量?例如,如果在imagesUrls中有399个项目(要下载的文件),那么在label3中我想看到一个计数器从399到0或每次下载文件完成并且被隔离时为1。

  4. 当它现在到达已完成的事件时,我得到例外:

  5.   

    e.Error = {“指数超出范围。必须是非负数且小于   集合的大小。\ r \ nParameter name:index“}

         

    在System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument)   参数,ExceptionResource资源)at   System.Collections.Generic.List`1.get_Item(Int32 index)at   SatelliteImages.Form1.backgroundWorker1_DoWork(对象发送者,   DoWorkEventArgs e)in   d:\ C-夏普\ SatelliteImages \ SatelliteImages \ SatelliteImages \ Form1.cs中:线   60点到   System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
      在System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object   参数)

    我尝试过的更新:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.IO;
    using System.Net;
    using System.Threading;
    
    namespace SatelliteImages
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                ExtractImages ei = new ExtractImages();
                ei.Init();
            }
    
    
    
            private async void Form1_Load(object sender, EventArgs e)
            {
                label1.Text = "0 %";
                progressBar1.Minimum = 0;
                progressBar1.Maximum = ExtractImages.imagesUrls.Count() - 1;
                await DoWork();
            }
    
            private async Task DoWork()
            {
                for (int i = 0; i < ExtractImages.imagesUrls.Count(); i++)
                {
                    using (var client = new WebClient())
                    {
                        await client.DownloadFileTaskAsync(ExtractImages.imagesUrls[i], @"C:\Temp\TestingSatelliteImagesDownload\" + i + ".jpg");
    
                        progressBar1.Value = i + 1;
                        double average = (double)(i + 1) / ExtractImages.imagesUrls.Count();
                        label1.Text = (Math.Round(average, 1) * 100).ToString() + " %";
                    }
                }
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
    
            }
        }
    }
    
    1. progressBar没有结束它停止在99%我认为它是99%。

    2. label1最后显示100%,但progressBar没有结束。

    3. 最后我也得到例外:

    4. 例外是在Program.cs上的行:

      Application.Run(new Form1());
      

      附加信息:调用目标引发了异常。

      System.Reflection.TargetInvocationException was unhandled
        HResult=-2146232828
        Message=Exception has been thrown by the target of an invocation.
        Source=mscorlib
        StackTrace:
             at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
             at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
             at System.Delegate.DynamicInvokeImpl(Object[] args)
             at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
             at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
             at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
             at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
             at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
             at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
             at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
             at System.Windows.Forms.Control.WndProc(Message& m)
             at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
             at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
             at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
             at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
             at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
             at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
             at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
             at System.Windows.Forms.Application.Run(Form mainForm)
             at SatelliteImages.Program.Main() in D:\C-Sharp\SatelliteImages\SatelliteImages\SatelliteImages\Program.cs:line 19
             at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
             at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
             at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
             at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
             at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
             at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
             at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
             at System.Threading.ThreadHelper.ThreadStart()
        InnerException: 
             HResult=-2146233086
             Message=Value of '399' is not valid for 'Value'. 'Value' should be between 'minimum' and 'maximum'.
      Parameter name: Value
             ParamName=Value
             Source=System.Windows.Forms
             StackTrace:
                  at System.Windows.Forms.ProgressBar.set_Value(Int32 value)
                  at SatelliteImages.Form1.<DoWork>d__2.MoveNext() in D:\C-Sharp\SatelliteImages\SatelliteImages\SatelliteImages\Form1.cs:line 46
               --- End of stack trace from previous location where exception was thrown ---
                  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
                  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                  at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
                  at SatelliteImages.Form1.<Form1_Load>d__1.MoveNext() in D:\C-Sharp\SatelliteImages\SatelliteImages\SatelliteImages\Form1.cs:line 35
               --- End of stack trace from previous location where exception was thrown ---
                  at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<>c.<ThrowAsync>b__6_0(Object state)
             InnerException: 
      

2 个答案:

答案 0 :(得分:1)

第1,第2和第4个问题:

您从两侧循环从0到包括(0到&lt; = count)。这意味着,你循环计数+ 1次。我不认为那是你的意图。要修复它,我建议你从i = 1开始。我建议不要使用i = 0而且我的数量会减少,因为根据您的计算,进度条不会为i = 0添加任何进度。虽然这些建议可能会有所帮助,但我强烈建议您将progressbar.Maximum值设置为count,并在每次下载文件后将值增加一个。

我怀疑你的计算是将除法的结果四舍五入到整数。因此,首先将i乘以100.0,然后执行除法。喜欢(i * 100.0)/(images_count)。

满足您的第3个要求:

请参阅MSDN示例 - https://msdn.microsoft.com/en-us/library/t9fzsyec(v=vs.110).aspx

答案 1 :(得分:1)

要解决问题,您需要在for循环中将<=替换为<

现在您可以看到async-await模式有用的原因,代码流程与任何普通代码一样。检查以下简单程序与您的程序相同:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private async void Form1_Load(Object sender, EventArgs e)
    {
        label1.Text = "0 %";
        progressBar1.Minimum = 0;
        progressBar1.Maximum = ExtractImages.imagesUrls.Count() - 1;
        await DoWork();
    }

    private async Task DoWork()
    {
        for (int i = 0; i < ExtractImages.imagesUrls.Count(); i++)
        {
            using (var client = new WebClient())
            {
                await client.DownloadFileTaskAsync(ExtractImages.imagesUrls[i], @"C:\Temp\TestingSatelliteImagesDownload\" + i + ".jpg");

                progressBar1.Value = i + 1;
                double average = (double)(i + 1) / ExtractImages.imagesUrls.Count();
                label1.Text = (Math.Round(average, 1) * 100).ToString() + " %";
            }
        }
    }
}

请注意,您可以使用IProgress<int>并从下载文件的代码中解密更新UI的代码:

private async void Form1_Load(Object sender, EventArgs e)
{
    label1.Text = "0 %";
    var progress = new Progress<int>();
    progress.ProgressChanged += Progress_ProgressChanged;
    await DoWork(progress);
}

private void Progress_ProgressChanged(Object sender, Int32 e)
{
     progressBar1.Value = e + 1;
     double average = ((double)(e + 1) / (ExtractImages.imagesUrls.Count()));
     label3.Text = (Math.Round(average, 1) * 100).ToString() + " %";
}

然后在下载文件后添加:

progress.Report(i);