title: Asynchronously copy large files while reporting progress to a progress bar (example?)
body: <p>I need to copy a number of large files and report progress back to the UI via a progress bar. </p>
  
  <p>I bought "C# 5.0 in a Nutshell". I'm on page 597. I have been reading about parallel programming. I am trying to accomplish what in my mind is quite simple based on some examples in this book, but I'm really struggling. There must be some gaps in my understanding. This is why I'm posting this question.</p>
  
  <p>I have looked into background workers, but find myself running into cross-threading compiler errors when I try to get progress.</p>
  
  <p>I've looked into async commands but find myself misunderstanding lambda expressions. That, or how to actually execute the task's code asynchronously from a button click, while still reporting progress back to the UI thread. </p>
  
  <p>I have poured over many of the existing questions/answers here, on MSDN, codeproject, asked a few questions myself here and had them downvoted. I just need one simple example I can wrap my brain around and I'll be well on my way. </p>
  
  <p>I'm confident that my answer is in async, Task.Run, File.Copy (maybe StreamReader/StreamWriter classes) and IProgress. The questions / answers I've found in my two weeks of research and trial and error are either incomplete, or too broad / too specific for some given scenario.</p>
  
  <p>I just need one working example of a UI with a progress bar, and a button that executes code in a new thread to copy a set of large files (or just one large file) and reports back progress. From there, I can play with it and tweak it to my needs and further my overall understanding.</p>
  
  <p><strong>Code adapted from Clint's answer, but still not updating progress correctly</strong></p>
  
  <p>This adaptation copies the file in an asynchronous task but updates progress from 0 to 100% only after the file has copied. Because I'm working with large files, processing progress based on number of files is not sufficient.</p>
  
  <p>So far, nothing I have found or tried addresses performing a copy asynchronously whilst updating the byte for byte progress %-age of a large file. </p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Windows.Forms;
  using System.Threading.Tasks;
  using System.IO;
  
  namespace CopyProgressWorking
  {
      public partial class Form1 : Form
      {
          public Form1()
          {
              InitializeComponent();
  
              string srcFile = @"C:\temp\BigFile.txt";
              string dstFile = @"C:\temp\temp2\BigFile.txt";
              button1.Click += (s, e) =&gt; DoCopy(srcFile, dstFile);
          }
  
          public async Task CopyFiles(Dictionary&lt;string, string&gt; files, Action&lt;int&gt; progressCallback)
          {
              for (var x = 0; x &lt; files.Count; x++)
              {
                  var item = files.ElementAt(x);
                  var from = item.Key;
                  var to = item.Value;
  
                  using (var outStream = new FileStream(to, FileMode.Create, FileAccess.Write, FileShare.Read))
                  {
  
                      using (var inStream = new FileStream(from, FileMode.Open, FileAccess.Read, FileShare.Read))
                      {
  
                          long size = inStream.Position;
                          Console.WriteLine("Filesize is {0}", size);
                          await inStream.CopyToAsync(outStream);
  
                      }
                  }
  
                  progressCallback((int)((x + 1) / files.Count) * 100);
              }
          }
  
          public async void DoCopy(string srcFile, string dstFile)
          {
              label1.Text = "Copying " + srcFile;
              await CopyFiles(new Dictionary&lt;string, string&gt;
              {
                  {srcFile, dstFile}
              },
              prog =&gt;
              {
                  Invoke((MethodInvoker)delegate {
                      progressBar1.Value = prog;
                      if (prog &gt;= 100)
                      {
                          label1.Text = "Copy complete!";
                      }
                  });
              });
          }
      }
  }
  </code></pre>