Given the following code in the DoWork() event of a BackgroundWorker object, how can the concept be converted to the Async/Await model?I wish to execute multiple downloads simultaneously in order to maximize bandwidth. I also will need to retain the ability to increment a progress bar on the dialog.Dim oChunks As SortedDictionary(Of String, Byte())Dim oFiles As List(Of FileInfo)Dim iChunk As IntegeroChunks = New SortedDictionary(Of String, Byte())oFiles = Service.Client.GetChunks(Me.Upload.UploadId, Me.Target)oFiles.ForEach(Sub(File As FileInfo)                 Worker.ReportProgress((iChunk / Me.Upload.Chunks) * 100, Downloading...)                 oChunks.Add(File.Name, Service.Client.GetChunk(File, Me.Target))                 iChunk += 1               End Sub)A C# answer is welcome; I can translate.EDITBased on Ewan's sample code, I came up with the revision below.But it's not working correctly:The downloads still run sequentially, not in parallelThe UI blocks during executionThe Download.Progress event doesn't fireWhat am I missing?Public Class Main  Private Async Sub cmdSave_Click(Sender As Button, e As EventArgs) Handles cmdSave.Click    Dim oChunks As SortedDictionary(Of String, Byte())    Dim oFiles As List(Of FileInfo)    Dim aData As Byte()    Me.Upload = dgvUploads.CurrentRow.DataBoundItem    pnlTarget.Enabled = False    dlgSave.FileName = {0}.zip.ToFormat(Me.Upload.UploadName)    txtFile.Text = String.Empty    If dlgSave.ShowDialog = DialogResult.OK Then      Me.SetControlsEnabled(False)      'bgwWorker.RunWorkerAsync(JobTypes.Save)      oFiles = Await Me.GetFilesAsync(Me.Upload.UploadId, Me.Target)      oChunks = Await Me.GetChunksAsync(oFiles)      aData = Await Me.MergeChunksAsync(oChunks)      File.WriteAllBytes(dlgSave.FileName, aData)      Me.SetControlsEnabled(True)      MsgBox(Download complete., MsgBoxStyle.Information, Me.Text)    End If  End Sub  Public Async Function GetFilesAsync(UploadId As Integer, Target As Targets) As Task(Of List(Of FileInfo))    Dim oArgs As ProgressEventArgs    oArgs = New ProgressEventArgs(0, Initializing..., ProgressBarStyle.Marquee)    Me.ReportProgress(Nothing, oArgs)    Return Await Service.Client.GetFilesAsync(UploadId, Target)  End Function  Public Async Function GetChunksAsync(Files As List(Of FileInfo)) As Task(Of SortedDictionary(Of String, Byte()))    Dim oDownload As Download    Dim oChunks As SortedDictionary(Of String, Byte())    Dim aChunks As Chunk()    Dim oTasks As List(Of Task(Of Chunk))    Dim oArgs As ProgressEventArgs    prgProgress.Value = 0    oArgs = New ProgressEventArgs(Files.Count, Downloading..., ProgressBarStyle.Continuous)    oTasks = New List(Of Task(Of Chunk))    Files.ForEach(Sub(File)                    oDownload = New Download                    AddHandler oDownload.Progress, AddressOf ReportProgress                    oTasks.Add(oDownload.GetChunkAsync(File, Me.Target, oArgs))                  End Sub)    aChunks = Await Task.WhenAll(oTasks.ToArray)    oChunks = New SortedDictionary(Of String, Byte())    aChunks.ToList.ForEach(Sub(Chunk)                             oChunks.Add(Chunk.Name, Chunk.Data)                           End Sub)    Return oChunks  End Function  Public Async Function MergeChunksAsync(Chunks As SortedDictionary(Of String, Byte())) As Task(Of Byte())    Dim oChunks As List(Of Byte())    Dim iOffset As Integer    Dim oArgs As ProgressEventArgs    Dim aData As Byte()    prgProgress.Value = 0    oArgs = New ProgressEventArgs(Chunks.Count, Saving..., ProgressBarStyle.Continuous)    aData = Await Task.Run(Function()                             oChunks = Chunks.Select(Function(Pair) Pair.Value).ToList                             aData = New Byte(oChunks.Sum(Function(Chunk) Chunk.Length) - 1) {}                             oChunks.ForEach(Sub(Chunk)                                               Me.ReportProgress(Nothing, oArgs)                                               Buffer.BlockCopy(Chunk, 0, aData, iOffset, Chunk.Length)                                               iOffset += Chunk.Length                                             End Sub)                             Return aData                           End Function)    Return aData  End Function  Public Sub ReportProgress(Sender As Download, e As ProgressEventArgs)    prgProgress.Maximum = e.Maximum    prgProgress.Style = e.Style    If e.Style = ProgressBarStyle.Marquee Then      prgProgress.Value = 0    Else      prgProgress.Increment(1)    End If    lblStatus.Text = e.Status  End SubEnd ClassPublic Class Download  Public Event Progress As EventHandler(Of ProgressEventArgs)  Public Async Function GetChunkAsync(File As FileInfo, Target As Targets, Args As ProgressEventArgs) As Task(Of Chunk)    Dim oChunk As Chunk    oChunk = New Chunk    oChunk.Name = File.Name    oChunk.Data = Await Service.Client.GetChunkAsync(File, Target)    RaiseEvent Progress(Me, Args)    Return oChunk  End FunctionEnd ClassPublic Class Chunk  Public Property Name As String  Public Property Data As Byte()End ClassPublic Class ProgressEventArgs  Inherits EventArgs  Public Sub New(Maximum As Integer, Status As String, Style As ProgressBarStyle)    _Maximum = Maximum    _Status = Status    _Style = Style  End Sub  Public ReadOnly Property Maximum As Integer  Public ReadOnly Property Status As String  Public ReadOnly Property Style As ProgressBarStyleEnd Class
Need Async/Await equivalent for BackgroundWorker
asynchronous programming;async
Maybe something like this:public class Download    {        public EventHandler<int> Progress;        public async Task GetData(string url)        {            int percentDone = 0;            foreach (var chunk in chunks)            {                //get data                //write data to disk?                if(Progress != null)                {                    Progress(this, percentDone);                }            }        }    }    public class ManyDownloads    {        public void ReportProgress(object sender, int progress)        {            //update the UI        }        public List<Download> Downloads { get; set; }        public void DownloadAll(List<string> Urls)        {            this.Downloads = new List<Download>();            foreach(var url in Urls)            {                var d = new Download();                d.Progress += ReportProgress;                d.GetData(url); //dont await will run async                this.Downloads.Add(d); //keep hold of the download object so you can refernce it in ReportProgress if needed            }        }    }if you need the return value of the function you can add all the tasks to an array and use await Task.WhenAll or Task.WaitAllpublic async Task DownloadAll(List<string> Urls){    List<Task<string>> tasks = new List<Task<string>>();    this.Downloads = new List<Download>();    foreach(var url in Urls)    {        var d = new Download();        d.Progress += ReportProgress;        tasks.Add(d.GetData(url)); //dont await will run async    }    //tasks are all running in threads at this point    await Task.WhenAll<string>(tasks.ToArray()); //wait for all the tasks to complete before continuing    foreach(var t in tasks)    {        //save data        File.WriteAllText(t.Result, filename.txt); //todo::check for exceptions    }}Update re comments:The confusion is that the async keyword on the GetData function adds no functionality to the pseudo code. without an await within that function the code in that function executes synchronously. (I added the async because I assumed that the actual download chunk code will include an await.)However! we don't particularly care in this case about the code in the function. We want to run the whole function multiple times in parallel. Calling a Task function without awaiting it in the DownloadAll method creates and runs a new Task for each download.You have to be careful not to dispose of these Tasks before they are completed though. If you just ran the first set of code in a console app the app would start all the downloads and then finish and exit before they completed.