I tried many different ways to solve this problem, but I didn't find a solution. I tried to implement delegate and events, but they don't work in my case (I explain later why).
I've an application form (windows form - .NET Framework) where is instantiated a progress bar.
I need to update the progress bar based on the event trigger from an abstract class (example: there are many different button, with different functions, and i need to update the value of progress bar based on the button clicked).
The main problem is:
The functions linked to the button are inside an abstract class, which is instantiated dynamically:
public abstract class BaseClass
{
public void FirstJob()
...
public void SecondJob()
...
}
MainForm (where progressbar is located):
public partial class frmMain : MetroFramework.Forms.MetroForm
{
private async void btnCorris_Click(object sender, EventArgs e)
{
// Dynamically instance an object
string objectToInstantiate = $"{namespaces}.Proto.{btnCorry.Text}, Converx";
var objectType = Type.GetType(objectToInstantiate);
dynamic instantiatedObject = Activator.CreateInstance(objectType);
await Task.Run(() =>
{
instantiatedObject.Generate(checkBoxClear.Checked); // this function should update the progressbar
});
....
}
...
}
Of course I can not directly refer to the progress bar from the BaseClass because there is a cross thread exception, and I can not use events because the class is abstract so I can not directly refer at the event inside of it...
I was thinking about create a class which is inherited from BaseClass but I don't think is the right way to do it, and since I am not that expert i tried at first to look around (even on ChatGPT) to find a solution ... then I tought about write here and ask at the experts, what is the correct way to implement it.
The typical way would be to give your method a Progress<T>
object that it reports progress to. This takes care of the cross threading issue. So your code could look something like
private async void btnCorris_Click(object sender, EventArgs e)
{
...
var progress = new Progress<double>();
progress.ProgressChanged += UpdateProgress;
try{
await Task.Run(() => instantiatedObject.Generate(checkBoxClear.Checked, progress ));
}
finally{ progress.ProgressChanged -= UpdateProgress; }
}
private void UpdateProgress(object sender, double v){
// Update the progress bar
}
If you use a non modal progress bar you need to figure out what should happen if the user press a second button before the first one has finished: