I'm trying to add a progress bar to a working theaded program that uses a cancelation token too. The structure of the program is:
I have a button "BeginButton" that calls the function "MyFunction()". The function runs in another thread and
a cancellation token listens if I press a Cancel button. I needed to add the thread since the UI freezes when
MyFunction() runs and I wasn't able to stop it.
Since the MyFunction() reads a file in chunks of 1024 bytes, my logic to show the progress is get the 1% of
File.Length and check when the loop increases each 1% of File size. Then I increment the progressBaar1
when Module of "BytesRead" and "(1% of File size)" = 0, this is "BytesRead % OnePercent == 0". This logic
works in a program that doesn't use threads, but in my code with thread is not working.
How can I add the progress bar to my code?
I've added the progressBar1 control to the Form and added this code inside the while loop of my threaded program.
FileLength = (int)reader.BaseStream.Length; //Filename size
//Getting the 1% of FileName size
decimal OnePercent = Math.Truncate((Decimal)(FileLength/1024)/100);
if ( BytesRead % OnePercent == 0 && progressBar1.Value < 100)
{
progressBar1.Value++;
progressBar1.CreateGraphics().DrawString(
progressBar1.Value.ToString() + "%",
new Font("Arial",(float)8.25),Brushes.Black,100,5);
}
BytesRead++;
But I get this error:
System.Reflection.TargetInvocationException:
Exception has been thrown by the target of an invocation.
---> System.InvalidOperationException:
Cross-thread operation not valid: Control 'progressBar1' accessed from a thread
other than the thread it was created on.
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.Control.SendMessage(Int32 msg, Int32 wparam, Int32 lparam)
at System.Windows.Forms.ProgressBar.UpdatePos()
at System.Windows.Forms.ProgressBar.set_Value(Int32 value)
at DumpDecode1.MainForm.GetRecords(String fileName, CancellationToken token)
The was how it looks the program is:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AddingProgressBar
{
public partial class MainForm : Form
{
// Create the token source.
CancellationTokenSource cts = new CancellationTokenSource();
public MainForm()
{
InitializeComponent();
}
async void BeginButton_Click(object sender, EventArgs e)
{
if (cts != null)
{
cts.Cancel();
}
cts = new CancellationTokenSource();
await Task.Run(() => MyFunction(filename, cts.Token), cts.Token);
}
public void MyFunction(string inputfile, CancellationToken token)
{
int BytesRead = 0;
using (BinaryReader reader = new BinaryReader(File.Open(inputfile, FileMode.Open)))
{
FileLength = (int)reader.BaseStream.Length; //Filename size
//Getting the 1% of FileName size
decimal OnePercent = Math.Truncate((Decimal)(FileLength/1024)/100);
while (chunk.Length > 0) //The while loop runs Filename.Size/1024 times
{
if (token.IsCancellationRequested) { break; } // ### To Cancel Thread ###
chunk = reader.ReadBytes(1024);
//Some more code
// ######### Code added for Progress Bar #########
//Checking while loop grows up in 1 percent
if ( BytesRead % OnePercent == 0 && progressBar1.Value < 100)
{
progressBar1.Value++;
progressBar1.CreateGraphics().DrawString(
progressBar1.Value.ToString() + "%",
new Font("Arial",(float)8.25),Brushes.Black,100,5);
}
BytesRead++;
// ######### Code added for Progress Bar #########
}
}
}
}
}