2016-12-29 39 views
0
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%?爲什麼在下載圖片時progressBar從來沒有達到100%,我越來越遠離例外?

  2. 是我計算reportProgress和從i = 0開始的FOR循環的方式是好的嗎?

  3. 如何在窗體上顯示新標籤,例如label3,並顯示剩餘的文件數量以下載?例如,如果在imagesUrls中有399個項目(要下載的文件),那麼在label3中,我希望每次文件下載完成並進行處理時,都能看到從399到0或1的計數器。

  4. 當它現在越來越來完成的事件我得到異常:

e.Error = {「索引超出範圍必須爲非負數且小於 的。集合的大小\ r \ n參數名:索引「}

在System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument 說法,ExceptionResource資源)在 System.Collections.Generic.List`1.get_Item(的Int32指數)在 SatelliteImages.Form1.backgroundWorker1_DoWork(對象發件人, DoWorkEventArgs e)如 d:\ C-夏普\ SatelliteImages \ SatelliteImages \ SatelliteImages \ Form1.cs中:行 60在 System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs E)
在System.ComponentModel.BackgroundWorker.WorkerThreadStart(對象 參數)的是我的嘗試

更新:

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. 最終我也越來越例外:

唯一的例外是在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: 
+1

爲什麼你不只是有'progressBar1.Maximum = ExtractImages.imagesUrls.Count()'和避免所有這些計算。是的,從0開始是正確的。你的目標是什麼版本的.NET框架? 4.5和更高? – user3185569

+0

@ user3185569我使用的目標在這個項目.NET 4.5.2 –

+0

@ user3185569看我與更新部分請我還評論了您的解決方案更新的問題。謝謝。 –

回答

1

爲了您的第一,第二和第四個問題:

您是從0循環計數包(0至< =計數)在兩側。這意味着,你正在循環計數+1次。我不認爲這是你的意圖。爲了解決這個問題,我建議你從i = 1開始。我建議反對與i = 0去,我減少計數,因爲根據您的計算,進度條不會爲i = 0添加任何進度。雖然這些建議可能會有所幫助,我強烈建議您設置progressbar.Maximum值來計算每個文件下載後僅增加progressbar.Value一個。

我懷疑你的計算四捨五入劃分爲整數的結果。所以,首先用100.0乘以i,然後執行除法。像(我* 100.0)/(images_count)。

對於您的第三個要求:

請參考MSDN例 - https://msdn.microsoft.com/en-us/library/t9fzsyec(v=vs.110).aspx

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); 
+0

我現在嘗試了你的代碼。最後,progressBar並沒有達到100%,而是非常接近99%。 label1顯示100%。所以需要修復。並且在完成下載文件的整個過程後,我也會收到異常。 Program.cs中有個例外,我會用我所做的和異常來更新我的問題。 –

+0

另一件事的VAR進步是Form1_Load的我無法使用/從Progress_ProgressChanged事件調用它的內部。其次,進度變量沒有屬性Report。所以我不能鍵入progress.Report(i);因爲沒有Report屬性。如果您可以向我展示更新progressBar1 label1和label3的完整代碼,它將會很棒。謝謝。 –