Compile Error With BackgroundWorker [duplicate] - c#

This question already has answers here:
Passing Parameter to Backgroundworker
(3 answers)
Closed 7 years ago.
I am wanting to pass an additional parameter to my DoWork method, but am getting a compile error of No overload for 'backgroundWorker1_DoWork' matches delegate 'System.ComponentModel.DoWorkEventHandler'
This is my syntax, what should I do to fix this?
namespace Testing
{
public partial class Form1 : Form1
{
public static string[] employeeName;
public Form1()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1WorkerSupportsCancellation = true;
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
}
private void btn1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync(employeeName);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e, string[] employeeName)
{
//Just for example sake
for (int q = employeeName.GetLowerBound(0); q <= employeeName.GetUpperBound(0); q++)
{
MessageBox.Show(employeeName[q];
}
}
}
}

DoWorkEventHandler has the following definition :
public delegate void DoWorkEventHandler(
Object sender,
DoWorkEventArgs e
)
You cannot add a third argument. The object you want to get is in DoWorkEventArgs.Argument property.
public partial class Form1 : Form1
{
public static string[] employeeName;
public Form1()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1WorkerSupportsCancellation = true;
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
}
private void btn1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync(employeeName);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string[] employeeName = (string[])e.Argument;
//Just for example sake
for (int q = employeeName.GetLowerBound(0); q <= employeeName.GetUpperBound(0); q++)
{
MessageBox.Show(employeeName[q];
}
}
}

Related

Multiple process BackgroundWorker with classes

I make an application with WPF. I use a method in another class that goes through all the images in the folder from the MainForm class. I want the ProgressBar to be updated, so I send a request to this class to check for changes in the number of images processed. But it does not even process images. I use the BackgroundWorker class to do this. The MainForm code below:
public partial class MainWindow : Window
{
ImageProcessing detector;
BackgroundWorker worker;
public MainWindow()
{
InitializeComponent();
}
private void StartButton_Click(object sender, RoutedEventArgs e)
{
if (PathTextBox.Text != "")
{
detector = new ImageProcessing(isFolder, PathTextBox.Text);
worker.RunWorkerAsync();
}
}
private void MainForm_ContentRendered(object sender, EventArgs e)
{
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += Worker_CheckChangingProcessedImages;
worker.DoWork += Worker_RunProcessingImages;
worker.ProgressChanged += Worker_ProgressChanged;
}
private void Worker_RunProcessingImages(object sender, DoWorkEventArgs e)
{
detector.DetectTextOnImage();
}
private void Worker_CheckChangingProcessedImages(object sender, DoWorkEventArgs e)
{
while (detector.ReturnNumberProcessedImages() <= Progress.Maximum)
(sender as BackgroundWorker).ReportProgress(detector.ReturnNumberProcessedImages());
}
private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
int numberProcessed = detector.ReturnNumberProcessedImages();
Progress.Value = numberProcessed;
if (numberProcessed == 0) LogTextBox.Text = "Start processing";
else if ((numberProcessed == 1) && (Progress.Maximum == 1))
LogTextBox.Text += "\n1 image is processed";
else if (numberProcessed % 10 == 0)
LogTextBox.Text += $"\n{numberProcessed} images are processed";
if (numberProcessed == Progress.Maximum)
LogTextBox.Text += "\nEverything is processed";
}
}
The ImageProcessing class has a field with the number of processed images. The DetectTextOnImage() method has a foreach loop. The code below:
private int numberProcessedImages = 0;
public void DetectTextOnImage()
{
foreach (String imageFileName in Directory.GetFiles(path))
{
// do something
numberProcessedImages++;
}
}

Multiple Classes Read From Single Class

I am working on a project which requires to start a Timer on load of the Form1 that increments the TimerCount Property of Class TimeCounter in the tick event.
The Project has also Form2 which when open I want to read the increment updates from TimeCounter class which is being incremented by the Form1 because Form1 is parent and will not close I tried to read from TimeCounter but got default set value which is 0.
Here is code:
Timer Class
public class TimeCounter
{
public int timer=0;
public int TimerCount { get; set; }
public int GetTime()
{
return timer;
}
}
Form1 Increment TimerCount After 1 Second
private void Form1_Load(object sender, EventArgs e)
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.Elapsed += timer_Elapsed;
timer.Start();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
sk++;
Timer t = new Timer();
t.TimerCount = sk;
}
Form2 Which Receive Counter Continuously(But Not Working)
private void Form1_Load(object sender, EventArgs e)
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.Elapsed += timer_Elapsed;
timer.Enabled = true;
timer.Start();
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Timer t1 = new Timer();
B01CountDown.Text = t1.GetTime().ToString();
}
You are not passing the Timer object correctly to Form2. You need to pass the instance of Timer being used by form 1 to form 2.
Timer:
public class Timer
{
public int timer = 0;
public int TimerCount { get; set; }
public int GetTime()
{
return timer;
}
}
Form1:
public partial class Form1 : Form
{
private Timer _timer;
public Form1()
{
InitializeComponent();
_timer = new Timer();
timer1.Start();
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Tick += timer1_Tick;
}
void timer1_Tick(object sender, EventArgs e)
{
_timer.TimerCount++;
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2(_timer);
frm2.ShowDialog();
}
}
Form2:
public partial class Form2 : Form
{
public Timer _timer;
public Form2(Timer timer)
{
InitializeComponent();
_timer = timer;
timer1.Start();
}
private void Form2_Load(object sender, EventArgs e)
{
timer1.Tick += timer1_Tick;
}
void timer1_Tick(object sender, EventArgs e)
{
label1.Text = _timer.TimerCount.ToString();
}
}
Output:
I have modified the code you have posted as follows. If you do not understand, then you need to start learning C#.
TimeCounter:
public class TimeCounter
{
public static int timer = 0;
public static int TimerCount
{
get
{
return timer;
}
set
{
timer = value;
}
}
}
Form1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
new Form2().Show();
}
private void Form1_Load(object sender, EventArgs e)
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.Elapsed += timer_Elapsed;
timer.Start();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
TimeCounter.TimerCount++;
}
}
Form 2:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.Elapsed += timer_Elapsed;
timer.Enabled = true;
timer.Start();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (B01CountDown.InvokeRequired)
{
B01CountDown.Invoke((MethodInvoker)(() =>
{
B01CountDown.Text = TimeCounter.TimerCount.ToString();
}));
}
}
}
Actually you don't require TimeCounter Class and also Timer in Form2
see below code
Form1
public partial class Form1 : Form
{
int sk = 0;
Form2 form2 = new Form2();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.Elapsed += timer_Elapsed;
timer.Start();
}
private void button1_Click_1(object sender, EventArgs e)
{
form2.Show();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// Do your Stuff
sk++;
form2.UpdateLabel(sk.ToString());
}
}
Form2
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public void UpdateLabel(string Message)
{
if (B01CountDown.InvokeRequired)
{
B01CountDown.Invoke((MethodInvoker)(() =>
{
B01CountDown.Text = Message;
}));
}
}
}

increment the textbox using multithreading

I want to create a C# form in which two text box show two different numbers.
After clicking on start button both numbers should start incrementing at same time should increment slowly so we can see them increment and clicking on stop button should stop increment.
Both text box are not related to each other any way.
public partial class Form1 : Form
{
Thread t1 = new Thread(new ThreadStart(increment1));
public static int fNumber = 0, sNumber = 0,flag = 0;
public Form1()
{
InitializeComponent();
}
private void Start_Click(object sender, EventArgs e)
{
t1.Start();
}
private void button4_Click(object sender, EventArgs e)
{
}
private void number1_TextChanged(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
public static void increment1()
{
Form1 frm = new Form1();
for (int i = fNumber;i<1000;i++)
{
frm.number1.Text = Convert.ToString(i);
}
}
}
public void Increment1()
{
for (int i = fNumber;i<1000;i++)
{
number1.Text = Convert.ToString(i);
number2.Text = Convert.ToString(i);
}
}
And just generally avoid static for threads. You can access your textboxes directly without the word this if you named your textboses number1 and number2. In a static method the variables need to be static aswell or you will get a compilation error.
For visibility, functions should have first letter in upper case. So you can distinguish them more easily from variables.
You are creating a new instance of Form1 which is wrong. Use the current Form1 that started the Thread.
Try
public partial class Form1 : Form
{
private Timer timer1;
public static int fNumber = 0, sNumber = 0,flag = 0;
public Form1()
{
timer1 = new Timer();
timer1.Interval = 1000;
timer1.Tick += timer1_Tick;
InitializeComponent();
}
private void Start_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void button4_Click(object sender, EventArgs e)
{
timer1.Stop();
}
private void number1_TextChanged(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
int i = 0;
int.TryParse(this.number1.Text, out i);
i++;
if(this.number1.InvokeRequired)
{
this.number1.BeginInvoke((MethodInvoker) delegate()
{
this.number1.Text = Convert.ToString(i);
});
}
else
{
this.number1.Text = Convert.ToString(i);
}
}
}
For safety measures, check if invoking is required.
Replace this.number1.Text = Convert.ToString(i); with this block of code.
if(this.number1.InvokeRequired)
{
this.number1.BeginInvoke((MethodInvoker) delegate()
{
this.number1.Text = Convert.ToString(i);
});
}
else
{
this.number1.Text = Convert.ToString(i);
}

BackgroundWorker does not fire inside User Control

I am currently creating a Windows Form Application and I am wanting to use a BackgroundWorker. I have created a very simple example which works perfectly:
public partial class Form1 : Form
{
private BackgroundWorker bgw = new BackgroundWorker();
public Form1()
{
InitializeComponent();
bgw.WorkerReportsProgress = true;
bgw.DoWork += new DoWorkEventHandler(DoWork);
bgw.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Completed);
}
private void button1_Click(object sender, EventArgs e)
{
bgw.RunWorkerAsync();
}
private void DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i <= 10; i++)
{
bgw.ReportProgress(i * 10, i.ToString());
Thread.Sleep(1000);
}
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = string.Format("{0}% : Message = '{1}'", e.ProgressPercentage, e.UserState.ToString());
}
private void Completed(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Completed");
}
}
Now, when I move the same code to my current application it does not fire. The only difference is that instead of running the code at the Form level, I am attempting to run it inside a custom User Control. As such:
public partial class LobbyForm : UserControl
{
private BackgroundWorker bgw = new BackgroundWorker();
public LobbyForm()
{
InitializeComponent();
bgw.WorkerReportsProgress = true;
bgw.DoWork += new DoWorkEventHandler(DoWork);
bgw.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Completed);
}
public LobbyForm(List<TaskFile> tasks)
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
bgw.RunWorkerAsync();
}
private void DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i <= 10; i++)
{
bgw.ReportProgress(i * 10, i.ToString());
Thread.Sleep(1000);
}
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label5.Text = string.Format("{0}% : Message = '{1}'", e.ProgressPercentage, e.UserState.ToString());
}
private void Completed(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Completed");
}
}
Any thoughts on if I am missing something? Perhaps something I am misunderstanding with attempting to run this from a User Control?
I just copied your code and tested it and it worked perfectly if you drag-drop the user control using the designer.
However, if you create he control at runtime and add it to your form, make sure you're using the correct constructor.
LobbyForm lf = new LobbyForm();
this runs this constructor:
public LobbyForm()
{
InitializeComponent();
bgw.WorkerReportsProgress = true;
bgw.DoWork += new DoWorkEventHandler(DoWork);
bgw.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Completed);
}
and not
LobbyForm lf = new LobbyForm(tasks);
which runs this constructor (that doesn't hook up events):
public LobbyForm(List<string> tasks)
{
InitializeComponent();
}
Solution (Call the default constructor from the second one)
public LobbyForm(List<string> tasks) : this()
{
//InitializeComponent();
}

How to abort a while loop by clicking a button using C#

I have a function that displays numbers using a while loop but I want to stop execution of a while loop at random variable value using c# by clicking a button.
For Example:
private void FrqSent()
{
int i = 1;
while (i <= 5)
{
i = i + 1;
}
}
Here is a quick example on how you can use a Backgroundworker to accomplish your task:
public partial class Form1 : Form
{
private int i = 1;
public Form1()
{
InitializeComponent();
}
private void FrqSent()
{
while (i <= 500000000)
{
if (backgroundWorker1.CancellationPending)
{
break;
}
else
{
i = i + 1;
}
}
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void button2_Click(object sender, EventArgs e)
{
backgroundWorker1.CancelAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
FrqSent();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show(i.ToString());
}
}
Just create a new Windows-Forms Project and add a backgroundworker object aswell as 2 buttons. You have to set the DoWork, RunWorkerCompleted and Click events manually.
Edit: Do not forget to set the BackgroundWorker`s WorkerSupportsCancellation property to true.
not very elegant but simple
public partial class Form1 : Form
{
private bool _stop;
public Form1()
{
InitializeComponent();
}
private void buttonStart_Click(object sender, EventArgs e)
{
_stop = false;
FrqSent();
}
private void buttonStop_Click(object sender, EventArgs e)
{
_stop = true;
}
private void FrqSent()
{
int i = 1;
while (i <= 5000000 && !_stop)
{
i = i + 1;
Application.DoEvents();
}
}
}

Categories