This is just sample test code that I'm trying to get to work. I know there are better ways to report progress but I just want to know why this code is not working. I'm reading a file and reporting progress, but it freezes the UI, and waits until the entire task is done.
private async void runtTasksButton_Click(object sender, RoutedEventArgs e)
{
List<Task> tasks = new List<Task>();
var t = Task.Factory.StartNew(() =>
{
FileStream fs = File.OpenRead(@"C:\Whatever.txt");
var totalLength = fs.Length;
this.Dispatcher.BeginInvoke(new Action(() =>
{
progressBar1.Maximum = totalLength;
}), null);
using (fs)
{
byte[] b = new byte[1024];
while (fs.Read(b, 0, b.Length) > 0)
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
progressBar1.Value += 1024;
}), null);
};
}
});
tasks.Add(t);
await Task.WhenAll(tasks.ToArray());
}
EDIT: I know about BackgroundWorker
and async/await
. But, I'm just trying to figure out this block of code in order to get a deeper understanding of the TPL
. I did use the FileStream.ReadAsync()
method and was able to update the ProgressBar
at runtime as such:
private void runtTasksButton_Click(object sender, RoutedEventArgs e)
{
progressTextBox.Text = "";
label1.Content = "Milliseconds: ";
progressBar1.Value = 0;
progressBar2.Value = 0;
var watch = Stopwatch.StartNew();
List<Task> tasks = new List<Task>();
var t1 = Task.Factory.StartNew(() => ReadFile(@"C:\BigFile1.txt", progressBar1));
var t2 = Task.Factory.StartNew(() => ReadFile(@"C:\BigFile2.txt", progressBar2));
tasks.Add(t1);
tasks.Add(t2);
Task.Factory.ContinueWhenAll(tasks.ToArray(),
result =>
{
var time = watch.ElapsedMilliseconds;
this.Dispatcher.BeginInvoke(new Action(() =>
label1.Content += time.ToString()));
});
}
private async Task ReadFile(string path, ProgressBar progressBar)
{
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None, 8192, true);
var totalLength = fs.Length;
await this.Dispatcher.BeginInvoke(new Action(() =>
{
progressBar.Maximum = totalLength;
}));
using (fs)
{
byte[] b = new byte[8192];
while (await fs.ReadAsync(b, 0, b.Length) > 0)
{
await this.Dispatcher.BeginInvoke(new Action(() =>
{
progressBar.Value += 8192;
}));
};
}
}
However, now the control goes into the ContinueWhenAll
without waiting for the file reading Tasks to complete. But the Tasks do update the respective ProgressBars as intended. If someone could give some explanations, that would be appreciated.