Cannot update Progress Bar when download in google drive in C# - c#

I'm using Google drive V3 api. I tried to updated progress when downloading file but it seems not working.
I used Dispatcher.BeginInvoke() to update progressbar value.
When I debug at progressBar.Value, it didn't jump into this line: progressBar.Value = Convert.ToDouble(progress.BytesDownloaded * 100 / fileSize);
I've searched in google and stackoverflow but I cannot find the solution.
Please help. Thank you in advanced!
MainWindow.xaml
<Window x:Class="DownloadProgress.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DownloadProgress"
mc:Ignorable="d"
Title="MainWindow" Height="150" Width="400">
<StackPanel>
<ProgressBar Height="30" Margin="10" Name="progressBar"/>
<Button Height="30" Content="Downloads" Margin="10" Click="StartDownload"/>
</StackPanel>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void StartDownload(object sender, RoutedEventArgs e)
{
string[] Scopes = { DriveService.Scope.DriveReadonly };
DriveService driveService = AuthenticateServiceAccount(#"C:\Users\210636\Downloads\licensemanage-cf129668e7ad.json", Scopes);
FilesResource.ListRequest listRequest = driveService.Files.List();
listRequest.Q = "'1Rl6E1sLkMdW0iRpfdrOzdF4C_U6lfZhu' in parents";
listRequest.PageSize = 10;
listRequest.Fields = "nextPageToken, files(id, name, size)";
IList<Google.Apis.Drive.v3.Data.File> files = listRequest.Execute().Files;
var fileId = "1QETWTnkIp9q6O35Rm99qC6LsJ4Gdg3I5";
var request = driveService.Files.Get(fileId);
request.Fields = "id, name, size";
var file = request.Execute();
long? fileSize = file.Size;
string f = driveService.Files.Get(fileId).Execute().Name;
var streamDownload = new MemoryStream();
progressBar.Minimum = 0;
progressBar.Maximum = 100;
progressBar.Value = 50;
request.MediaDownloader.ProgressChanged += (IDownloadProgress progress) =>
{
switch (progress.Status)
{
case DownloadStatus.Downloading:
{
Dispatcher.BeginInvoke(new Action(() =>
{
progressBar.Value = Convert.ToDouble(progress.BytesDownloaded * 100 / fileSize);
}));
break;
}
case DownloadStatus.Completed:
{
Console.WriteLine("Download complete.");
using (FileStream fs = new FileStream("downloaded.zip", FileMode.OpenOrCreate))
{
streamDownload.WriteTo(fs);
fs.Flush();
}
break;
}
case DownloadStatus.Failed:
{
break;
}
}
};
request.Download(streamDownload);
}
public static DriveService AuthenticateServiceAccount(string serviceAccountCredentialFilePath, string[] scopes)
{
GoogleCredential credential;
using (var stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream)
.CreateScoped(scopes);
}
// Create the Analytics service.
return new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Drive Service account Authentication Sample",
});
}
}

request.Download(streamDownload); is blocking the UI thread. The downloading should be async. I also highly recommend to use Progress<T> to report progress to the UI: Async in 4.5: Enabling Progress and Cancellation in Async APIs.
MainWindow.xaml.cs
// Asynchronous event handler
private async void StartDownloadAsync(object sender, RoutedEventArgs e)
{
...
var fileId = "1QETWTnkIp9q6O35Rm99qC6LsJ4Gdg3I5";
progressBar.Minimum = 0;
progressBar.Maximum = 100;
progressBar.Value = 50;
// Creating an instance of Progress<T> captures the current
// SynchronizationContext (UI context) to prevent cross threading when updating the ProgressBar
IProgress<double> progressReporter =
new Progress<double>(value => progressBar.Value = value);
await DownloadAsync(progressReporter, fileId);
}
private async Task DownloadAsync(progressReporter, string fileId)
{
var streamDownload = new MemoryStream();
var request = driveService.Files.Get(fileId);
var file = request.Execute();
long? fileSize = file.Size;
// Report progress to UI via the captured UI's SynchronizationContext using IProgress<T>
request.MediaDownloader.ProgressChanged +=
(progress) => ReportProgress(progress, progressReporter, fileSize, streamDownload);
// Execute download asynchronous
await Task.Run(() => request.Download(streamDownload));
}
private void ReportProgress(IDownloadProgress progress, IProgress<double> progressReporter, long? fileSize, MemoryStream streamDownload)
{
switch (progress.Status)
{
case DownloadStatus.Downloading:
{
double progressValue = Convert.ToDouble(progress.BytesDownloaded * 100 / fileSize);
// Update the ProgressBar on the UI thread
progressReporter.Report(progressValue);
break;
}
case DownloadStatus.Completed:
{
Console.WriteLine("Download complete.");
using (FileStream fs = new FileStream("downloaded.zip", FileMode.OpenOrCreate))
{
streamDownload.WriteTo(fs);
fs.Flush();
}
break;
}
case DownloadStatus.Failed:
{
break;
}
}
}

Related

Progressbar for 7zip compression in c#

The intention is to make a progress bar move according to the compression of files, but it only works in the decompression (not showed on code), where is the problem?
private void Compress(string source)
{
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;
progressBar1.Value = 0;
progressBar1.Visible = true;
var progressHandled =
new Progress<byte>(percentDone => progressBar1.Value = percentDone);
var progress = progressHandled as IProgress<byte>;
Task.Run(() =>
{
string SZpath = Directory.GetCurrentDirectory() + #"\64-7z.dll";
SevenZipBase.SetLibraryPath(SZpath);
SevenZipCompressor compressor = new SevenZipCompressor();
compressor.ArchiveFormat = OutArchiveFormat.Zip;
compressor.TempFolderPath = Path.GetTempPath();
compressor.CompressionMode = SevenZip.CompressionMode.Create;
compressor.CompressionLevel = SevenZip.CompressionLevel.Fast;
compressor.CompressionMethod = CompressionMethod.Lzma;
compressor.ZipEncryptionMethod = ZipEncryptionMethod.Aes256;
compressor.Compressing += (sender, args) =>
{
progress.Report(args.PercentDone);
};
compressor.CompressionFinished += (sender, args) =>
{
};
compressor.CompressDirectory(source, #"A:\C#\empty\archive.zip", "password");
});
log("Ended"); // the void is not on code
}
The code works perfectly, the problem is that the progressbar never moved
Thank you for your time, I look forward to your answer.

Reading large txt file async and reporting progress in progressbar WPF C# [duplicate]

This question already has answers here:
Read/Write text file progressbar in C#
(1 answer)
How to show progress of reading from a file and writing to a database
(1 answer)
Closed 1 year ago.
I am trying to read a large txt file (>50MB) asynchronously and while it is being read, report the progress on the UI progressbar and have the option to cancel the process. So far I have read and processed the file async as I wanted but I could not solve the progressbar part.
public static async Task<string> ReadTxtAsync(string filePath)
{
try
{
using (var reader = File.OpenText(filePath))
{
var content = await reader.ReadToEndAsync();
return content;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}
public static async Task<Dictionary<string, int>> OpenTxtAsync()
{
Dictionary<string, int> uniqueWords = new Dictionary<string, int>();
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Text Documents (*.txt)|*.txt";
string content = null;
try
{
if (openFileDialog.ShowDialog() == true)
{
string filePath = openFileDialog.FileName.ToString();
if (openFileDialog.CheckFileExists && new[] { ".txt" }.Contains(Path.GetExtension(filePath).ToLower()) && filePath != null)
{
Task<string> readText = ReadTxtAsync(filePath);
content = await readText;
uniqueWords = WordExtractor.CountWords(ref content);
}
else MessageBox.Show("Please use .txt format extension!");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return uniqueWords;
}
private async void LoadFileButtonClick(object sender, RoutedEventArgs e)
{
Task<Dictionary<string, int>> dictionaryContent = TextFileLoader.OpenTxtAsync();
uniqueWords = await dictionaryContent;
UpdateListView();
}
How can I check where ReadToEndAsync() is currently? How can I get it to continously update the progressbar and how can I cancel it?
EDIT:
Thanks to #emoacht I managed to get the progressbar to update correctly and display its percentage. The only thing that remains is to cancel the task, which I tried according to a Tim Corey video, but it did not work on my code.
public static async Task<string> ReadTextAsync(string filePath, IProgress<(double current, double total)> progress, CancellationToken cancellationToken)
{
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
using var reader = new StreamReader(stream);
var readTask = reader.ReadToEndAsync();
cancellationToken.ThrowIfCancellationRequested();
var progressTask = Task.Run(async () =>
{
while (stream.Position < stream.Length)
{
await Task.Delay(TimeSpan.FromMilliseconds(100));
progress.Report((stream.Position, stream.Length));
}
});
await Task.WhenAll(readTask, progressTask);
return readTask.Result;
}
try
{
Task<string> readText = TextFileLoader.ReadTextAsync(filePath, progress, cts.Token);
content = await readText;
LabelProgress.Content = "Done Reading! Now creating wordlist...";
}
catch (OperationCanceledException)
{
LabelProgress.Content = "File laden wurde abgebrochen";
}
I have a buttonClick Event for cancel cts.Cancel(); but the only part where it works is the Dictionary creation. If I place the cancellationToken.ThrowIfCancellationRequested(); into the progressbar update part, it stops only the update, the stream reading still continues. If I place is right below var readTask = reader.ReadToEndAsync(); it does nothing.
You can get the current position while reading by checking Stream.Position property at regular interval. The following method will check the current position once per 100 milliseconds and report it by current value of progress parameter. To use this method, instantiate Progess<(double current, double total)> and subscribe to its ProgressChanged event.
public static async Task<string> ReadTextAsync(string filePath, IProgress<(double current, double total)> progress)
{
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
using var reader = new StreamReader(stream);
var readTask = reader.ReadToEndAsync();
var progressTask = Task.Run(async () =>
{
while (stream.Position < stream.Length)
{
await Task.Delay(TimeSpan.FromMilliseconds(100));
progress.Report((stream.Position, stream.Length));
}
});
await Task.WhenAll(readTask, progressTask);
return readTask.Result;
}

Functions aren't finishing before starting the next

I have a youtube uploader, and I am generating a video from an audio file, which works fine, but when I am uploading to Youtube the program still runs when I am trying to wait for it to finish uploading before repeating
Here I generate a video:
private void button2_Click(object sender, EventArgs e)
{
if (status.Text == "Stopped")
{
if (!generatearticle.IsBusy)
{
// started
status.Text = "Started";
status.ForeColor = System.Drawing.Color.Green;
start.Text = "Stop Generating";
generatearticle.RunWorkerAsync();
}
}
else
{
if(generatearticle.IsBusy)
{
generatearticle.CancelAsync();
// started
status.Text = "Stopped";
status.ForeColor = System.Drawing.Color.Red;
start.Text = "Start Generating";
}
}
}
private void core()
{
// generate audio
int i = 0;
for (int n = 1; n < co; n++)
{
// generate video and upload to
// youtube, this generates, but
// when uploading to youtube this for
// loop carries on when I want it to
// upload to youtube first before carrying on
generatevideo(image, articlename);
}
}
private void generateVideo(string images, String articlename)
{
//generate the video here, once done upload
{code removed, this just generates a video, nothing important}
// now upload (but I want it to finish before repeating the core() function
try
{
new UploadVideo().Run(articlename, file);
}
catch (AggregateException ex)
{
foreach (var e in ex.InnerExceptions)
{
ThreadSafe(() =>
{
this.Invoke((MethodInvoker)delegate
{
status.Text = e.Message;
status.ForeColor = System.Drawing.Color.Red;
});
});
}
}
}
How I am uploading to Youtube:
using System;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Upload;
using Google.Apis.Util.Store;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;
namespace articletoyoutube
{
/// <summary>
/// YouTube Data API v3 sample: upload a video.
/// Relies on the Google APIs Client Library for .NET, v1.7.0 or higher.
/// See https://code.google.com/p/google-api-dotnet-client/wiki/GettingStarted
/// </summary>
class UploadVideo
{
// to access form controlls
Form1 core = new Form1();
public async Task Run(string articlename, string filelocation)
{
UserCredential credential;
using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
// This OAuth 2.0 access scope allows an application to upload files to the
// authenticated user's YouTube channel, but doesn't allow other types of access.
new[] {
YouTubeService.Scope.YoutubeUpload
},
"user",
CancellationToken.None
);
}
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = Assembly.GetExecutingAssembly().GetName().Name
});
var video = new Video();
video.Snippet = new VideoSnippet();
video.Snippet.Title = articlename;
video.Snippet.Description = "News story regarding" + articlename;
video.Snippet.Tags = new string[] {
"news",
"breaking",
"important"
};
video.Snippet.CategoryId = "25"; // See https://developers.google.com/youtube/v3/docs/videoCategories/list
video.Status = new VideoStatus();
video.Status.PrivacyStatus = "public"; // or "private" or "public"
var filePath = filelocation; // Replace with path to actual movie file.
using (var fileStream = new FileStream(filePath, FileMode.Open))
{
var videosInsertRequest = youtubeService.Videos.Insert(video, "snippet,status", fileStream, "video/*");
videosInsertRequest.ProgressChanged += videosInsertRequest_ProgressChanged;
videosInsertRequest.ResponseReceived += videosInsertRequest_ResponseReceived;
await videosInsertRequest.UploadAsync();
}
}
void videosInsertRequest_ProgressChanged(Google.Apis.Upload.IUploadProgress progress)
{
switch (progress.Status)
{
case UploadStatus.Uploading:
core.prog_up.Text = "{0} bytes sent." + progress.BytesSent;
break;
case UploadStatus.Failed:
core.status.Text = "An error prevented the upload from completing.\n{0}" + progress.Exception;
core.status.ForeColor = System.Drawing.Color.Red;
break;
}
}
void videosInsertRequest_ResponseReceived(Video video)
{
core.prog_up.Text = "Video id '{0}' was successfully uploaded." + video.Id;
}
}
}
The background worker just runs core();
When it reaches the function
new UploadVideo().Run(articlename, file);
It starts uploading but starts repeating the core function again thus generating another video before that video has uploaded.... If I use
new UploadVideo().Run(articlename, file).Wait();
Then the program just stops and waits indefintly until I close the program, how can I wait for the Upload class/method to finish before carrying on with the fore loop in the core method?
To the guy who answered, when I add await before the new Upload... it gives me:
Severity Code Description Project File Line Suppression State
Error CS4033 The 'await' operator can only be used within an async
method. Consider marking this method with the 'async' modifier and
changing its return type to
'Task'. articletoyoutube C:\Users\Laptop\Documents\Visual Studio
2017\Projects\articletoyoutube\articletoyoutube\Form1.cs 254 Active
Make sure the async keyword is used on your methods and use the await keyword for the Tasks.
For example:
private async Task core()
{
// generate audio
int i = 0;
for (int n = 1; n < co; n++)
{
await generatevideo(image, articlename);
}
}
private async Task generateVideo(string images, String articlename)
{
//generate the video here,
try
{
var uploadVideo = new UploadVideo();
await uploadVideo.Run(articlename, file);
}
catch (AggregateException ex)
{
foreach (var e in ex.InnerExceptions)
{
ThreadSafe(() =>
{
this.Invoke((MethodInvoker)delegate
{
status.Text = e.Message;
status.ForeColor = System.Drawing.Color.Red;
});
});
}
}
}
You need to use await all the way up your call stack to where your event handler is, this will require changing many of your methods.
private async Task core()
{
// generate audio
int i = 0;
for (int n = 1; n < co; n++)
{
// generate video and upload to
// youtube, this generates, but
// when uploading to youtube this for
// loop carries on when I want it to
// upload to youtube first before carrying on
await generatevideo(image, articlename);
}
}
private async Task generateVideo(string images, String articlename)
{
//generate the video here, once done upload
{code removed, this just generates a video, nothing important}
// now upload (but I want it to finish before repeating the core() function
try
{
await new UploadVideo().Run(articlename, file);
}
catch (AggregateException ex)
{
foreach (var e in ex.InnerExceptions)
{
ThreadSafe(() =>
{
this.Invoke((MethodInvoker)delegate
{
status.Text = e.Message;
status.ForeColor = System.Drawing.Color.Red;
});
});
}
}
}
Note, using async/await does not work with BackgroundWorker you will need to switch to using Task.Run and a CancellationToken to signal cancellation.
Task _backgroundWork;
CancellationTokenSource _cts;
private void button2_Click(object sender, EventArgs e)
{
if (status.Text == "Stopped")
{
if (!generatearticle.IsBusy)
{
// started
status.Text = "Started";
status.ForeColor = System.Drawing.Color.Green;
start.Text = "Stop Generating";
_cts = new CancellationTokenSource();
_backgroundWork = Task.Run(() => core(_cts.Token), _cts.Token);
}
}
else
{
if(!_backgroundWork.IsCompleted)
{
_cts.Cancel();
// started
status.Text = "Stopped";
status.ForeColor = System.Drawing.Color.Red;
start.Text = "Start Generating";
}
}
}

RestSharp DownloadData sync with progressbar

How can I download file and show downloading progress by ProgressBar in window form app?
RestClient client = new RestClient("http://127.0.0.1/");
RestRequest request = new RestRequest("/test/{FileName}");
request.AddParameter("FileName", "testFile.abc", ParameterType.UrlSegment);
string path = #"C:/Users/[user]/Desktop/testFile.abc";
var fileForDownload = client.DownloadData(request);
fileForDownload.SaveAs(path);
if (File.Exists(#"C:/Users/[user]/Desktop/testFile.abc"))
{
MessageBox.Show("done");
}
I write somethink like this but I don't know what now?
I think a better alternative would be to override FileStream to get count of bytes written to file:
string tempFile = Path.Combine(Configuration.DownloadFolder, "TEST.DATA");
using (var writer = new HikFileStream(tempFile))
{
writer.Progress += (w, e) => {
#if DEBUG
Console.Write(string.Format("\rProgress: {0} / {1:P2}", writer.CurrentSize, ((double)writer.CurrentSize) / finalFileSize));
#endif
};
request.ResponseWriter = (responseStream) => responseStream.CopyTo(writer);
var response = client.DownloadData(request);
}
where HikFileStream is:
class HikFileStream : FileStream
{
public HikFileStream(string path)
: base(path, FileMode.Create, FileAccess.Write, FileShare.None)
{
}
public long CurrentSize { get; private set; }
public event EventHandler Progress;
public override void Write(byte[] array, int offset, int count)
{
base.Write(array, offset, count);
CurrentSize += count;
var h = Progress;
if (h != null)
h(this, EventArgs.Empty);//WARN: THIS SHOULD RETURNS ASAP!
}
}
Sorry but you can't, because there is no event handler object in RestClient to take status of download data.
Here is an alternative way to do it;
//...
timer1.Interval = 1000; // 1 sec interval.
timer1.Start();
RestClient client = new RestClient("http://127.0.0.1/")
{
Timeout = 10 * 1000 //10 sec timeout time.
};
RestRequest request = new RestRequest("/test/{FileName}");
request.AddParameter("FileName", "testFile.abc", ParameterType.UrlSegment);
string path = #"C:/Users/[user]/Desktop/testFile.abc";
var fileForDownload = client.DownloadData(request);
fileForDownload.SaveAs(path);
if (File.Exists(#"C:/Users/[user]/Desktop/testFile.abc"))
{
MessageBox.Show("done");
}
progressBar1.Value = 100;
timer1.Stop();
}
public void timer1_Tick(object sender, EventArgs e)
{
if (progressBar1.Value <= 100)
{
progressBar1.Value += 10;
}
if (progressBar1.Value >= 100)
{
progressBar1.Value = 0;
}
}
Change the name of "timer1" for naming-best-practices. Good luck...

error while adding progress bar to a method

i have been working on a windows store project using c#
i have a method called
void TranscodeProgress(IAsyncActionWithProgress<double> asyncInfo, double percent)
{
pg1.Value=percent;
}
when i try to add a progress bar to this it gives me an error
The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))
please help me to correct this error
thanks
this is my entire code
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
Windows.Storage.StorageFile source;
Windows.Storage.StorageFile destination;
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
openPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.VideosLibrary;
openPicker.FileTypeFilter.Add(".mp4");
openPicker.FileTypeFilter.Add(".wmv");
source = await openPicker.PickSingleFileAsync();
var savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.VideosLibrary;
savePicker.DefaultFileExtension = ".wmv";
savePicker.SuggestedFileName = "New Video";
savePicker.FileTypeChoices.Add("MPEG4", new string[] { ".wmv" });
destination = await savePicker.PickSaveFileAsync();
// Method to perform the transcoding.
TranscodeFile(source, destination);
}
async void TranscodeFile(StorageFile srcFile, StorageFile destFile)
{
MediaEncodingProfile profile =
MediaEncodingProfile.CreateWmv(VideoEncodingQuality.HD1080p);
MediaTranscoder transcoder = new MediaTranscoder();
PrepareTranscodeResult prepareOp = await
transcoder.PrepareFileTranscodeAsync(srcFile, destFile, profile);
if (prepareOp.CanTranscode)
{
var transcodeOp = prepareOp.TranscodeAsync();
transcodeOp.Progress +=
new AsyncActionProgressHandler<double>(TranscodeProgress);
// p1.Value = double.Parse(transcodeOp.Progress.ToString());
// txtProgress.Text = transcodeOp.Progress.ToString();
transcodeOp.Completed +=
new AsyncActionWithProgressCompletedHandler<double>(TranscodeComplete);
}
else
{
switch (prepareOp.FailureReason)
{
case TranscodeFailureReason.CodecNotFound:
MessageDialog md=new MessageDialog("Codec not found.");
await md.ShowAsync();
break;
case TranscodeFailureReason.InvalidProfile:
MessageDialog md1 = new MessageDialog("Invalid profile.");
await md1.ShowAsync();
break;
default:
MessageDialog md2 = new MessageDialog("Unknown failure.");
await md2.ShowAsync();
break;
}
}
//txtDisplay.Text = a;
}
void TranscodeProgress(IAsyncActionWithProgress<double> asyncInfo, double percent)
{
}
void TranscodeComplete(IAsyncActionWithProgress<double> asyncInfo, AsyncStatus status)
{
asyncInfo.GetResults();
if (asyncInfo.Status == AsyncStatus.Completed)
{
// Display or handle complete info.
}
else if (asyncInfo.Status == AsyncStatus.Canceled)
{
// Display or handle cancel info.
}
else
{
// Display or handle error info.
}
}
You should:
Avoid async void.
Use the TAP naming pattern (make your Task-returning methods end in "Async").
Use AsTask to do complex interop between TAP and WinRT asynchronous operations.
Something like this:
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
...
await TranscodeFileAsync(source, destination);
}
async Task TranscodeFileAsync(StorageFile srcFile, StorageFile destFile)
{
MediaEncodingProfile profile =
MediaEncodingProfile.CreateWmv(VideoEncodingQuality.HD1080p);
MediaTranscoder transcoder = new MediaTranscoder();
PrepareTranscodeResult prepareOp = await
transcoder.PrepareFileTranscodeAsync(srcFile, destFile, profile);
if (prepareOp.CanTranscode)
{
var progress = new Progress<double>(percent => { pg1.Value = percent; });
var result = await prepareOp.TranscodeAsync().AsTask(progress);
// Display result.
}
else
{
...
}
}
You are trying to access UI component from non UI Thread.
use:
void TranscodeProgress(IAsyncActionWithProgress<double> asyncInfo, double percent)
{
if(InvokeRequired)
{
Invoke(new MethodInvoker() => TranscodeProgress(asyncInfo, percent));
return;
}
pg1.Value=percent;
}
You cannot access UI components from non UI threads, Calling Invoke with a delegate passes the function call to thread that owns the component and than that thread call the passed delegate.

Categories

Resources