Search code examples
c#windows-runtimewinrt-async

BackgroundDownloader Max Parallelism


Is there a way to set the max number of concurrent downloads from BackgroundDownloader?

This is roughly what I'm doing.

var downloader = new BackgroundDownloader();
foreach( var uri in uriList )
{
    var download = downloader.CreateDownload( uri, storageFile );
    download.StartAsync().AsTask( cancellationTokenSource.Token, progress );
}

I'd like to be able to set a max download parallelism of say 4. Is this built in, or do I need to manage this myself?

If I need to manage this myself, what is the recommended way? I have thought about just doing a Parallel.ForEach and setting the max amount there, but I don't know if that's a good solution.


Solution

  • This is what I ended up doing. This isn't complete, but it's the gist of it.

    private void StartDownloadsAsync()
    {
        var downloadQueue = new Queue<DownloadOperation>();
        // Create all the download operations and add them to the queue.
        await CreateDownloadsAsync();
        var maxConcurrentDownloads = 4;
        var loopAmount = Math.Min( maxConcurrentDownloads, downloadQueue.Count );
        for( var i = 0; i < loopAmount; i++ )
        {
            DownloadAsync();
        }
    }
    
    private void DownloadAsync()
    {
        var download = downloadQueue.Dequeue();
    
        HandleDownloadAsync( download ).ContinueWith( task => DownloadComplete( download ) );
    }
    
    private void DownloadComplete( DownloadOperation download )
    {
        // Update progress counter here.
    
        if( downloadQueue.Count > 0 )
        {
            DownloadAsync();
        }
        else
        {
            // Downloads are done. Do something.
        }
    }
    
    private async Task HandleDownloadAsync( DownloadOperation download, bool isActive = false )
    {
        if( !isActive )
        {
            await download.StartAsync().AsTask( cancellationTokenSource.Token );
        }
        {
            await download.AttachAsync().AsTask( cancellationTokenSource.Token );
        }
    }