1

I am creating a download application in C# that downloads files from Amazon AWS S3 storage. I am able to download the file without issue, but I am trying to create a progress event.

To create the event I am using the following code within the download function:

Application.DoEvents();
response2.WriteObjectProgressEvent += displayProgress;
Application.DoEvents();

The event handler I created is as follows:

private void displayProgress(object sender, WriteObjectProgressArgs args)
{
    // Counter for Event runs
    label7.BeginInvoke(new Action(() => label7.Text = (Convert.ToInt32(label7.Text)+1).ToString()));

    Application.DoEvents(); 
    // transferred bytes
    label4.BeginInvoke(new Action(() => label4.Text = args.TransferredBytes.ToString()));

    Application.DoEvents();
    // progress bar
    progressBar1.BeginInvoke(new Action(() => progressBar1.Value = args.PercentDone));

    Application.DoEvents();
}

The issue is that it only updates when a file it downloaded, but the event runs more often. When I download the last file (12MB); lable7 (event counter) jumps from 3 to 121, so I know it is running, but just not updating.

I have also tried just a 'standard' Invoke, but I had the same result.

Additional Code of the function:

AmazonS3Config S3Config = new AmazonS3Config
{
    ServiceURL = "https://s3.amazonaws.com"
};

var s3Client = new AmazonS3Client(stuff, stuff, S3Config);

ListBucketsResponse response = s3Client.ListBuckets();

GetObjectRequest request = new GetObjectRequest();
request.BucketName = "dr-test";
request.Key = locationoffile[currentdownload];


GetObjectResponse response2 = s3Client.GetObject(request);

response2.WriteObjectProgressEvent += displayProgress;


string pathlocation = Path.GetDirectoryName(Directory.GetCurrentDirectory()) + "\\" + Instrument[currentdownload] + "\\" + NewFileName[currentdownload];

response2.WriteResponseStreamToFile(pathlocation);
ikaikastine
  • 601
  • 8
  • 22
user1433164
  • 101
  • 8

1 Answers1

0

You're not using the asynchronous call for GetObject or WriteResponseStreamToFile, so the UI thread (that you're calling it from) is going to be blocked, which means that it can't update the progress (regardless of those DoEvents calls, which are generally considered evil and you should avoid).

Without actually being able to try it myself, here's what I think you need to do.

private async void Button_Click(object sender, EventArgs e)
{
   foreach(...download....in files to download){

        AmazonS3Config S3Config = new AmazonS3Config
        {
            ServiceURL = "https://s3.amazonaws.com"
        };

        var s3Client = new AmazonS3Client(stuff, stuff, S3Config);

        ListBucketsResponse response = s3Client.ListBuckets();

        GetObjectRequest request = new GetObjectRequest();
        request.BucketName = "dr-test";
        request.Key = locationoffile[currentdownload];



        GetObjectResponse response2 = await s3Client.GetObjectAsync(request, null);

        response2.WriteObjectProgressEvent += displayProgress;



        string pathlocation = Path.GetDirectoryName(Directory.GetCurrentDirectory()) + "\\" + Instrument[currentdownload] + "\\" + NewFileName[currentdownload];

        await response2.WriteResponseStreamToFileAsync(pathlocation, null);

  }
 }

The two nulls that I added are for cancellation tokens, I can't tell from the AWS docs if it's allowed to pass a null token, if not please create one and pass it in.

Jim W
  • 4,866
  • 1
  • 27
  • 43
  • Thank you. I had to only change the WriteResponceStream line, and I did have to create a cancellation token. After that it worked without issue. – user1433164 Jun 02 '18 at 00:06