private static void UploadPartCopyCallback(IAsyncResult ar) { var result = client.EndUploadPartCopy(ar); var wrappedContext = (UploadPartCopyContextWrapper)ar.AsyncState; var ctx = wrappedContext.Context; lock (ctx.SyncLock) { var partETags = ctx.PartETags; partETags.Add(new PartETag(wrappedContext.PartNumber, result.ETag)); ctx.CompletedParts++; if (ctx.CompletedParts == ctx.TotalParts) { partETags.Sort((e1, e2) => (e1.PartNumber - e2.PartNumber)); var completeMultipartUploadRequest = new CompleteMultipartUploadRequest(ctx.TargetBucket, ctx.TargetObject, ctx.UploadId); foreach (var partETag in partETags) { completeMultipartUploadRequest.PartETags.Add(partETag); } var completeMultipartUploadResult = client.CompleteMultipartUpload(completeMultipartUploadRequest); Console.WriteLine(@"Async upload multipart copy result : " + completeMultipartUploadResult.Location); ctx.WaitEvent.Set(); } } }