Reputation: 9
I am having an issue with backgroundworker in c#. I am coding a dll file.
This is my code in a Class Library (.NET Framework) type project within VS 2019:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace States
{
public class ST
{
public static void Read()
{
BackgroundWorker bgwMessage = new BackgroundWorker();
bgwMessage.DoWork += new DoWorkEventHandler(BgwFileOpen_DoWork);
bgwMessage.RunWorkerAsync();
}
private static void BgwFileOpen_DoWork(object sender, DoWorkEventArgs e)
{
MessageBox.Show("Ran");
}
}
}
When I call the Read()
method using the Immediate window the command in background worker's DoWork
method does not run. Debguging the problem line by line shows that the Read()
method is running but it does not call RunworkerAsync somehow.
*Update1: starting a thread also did not work either:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TradeStates
{
public class ST
{
public static void Read()
{
Thread thr = new Thread(new ThreadStart(MSGshow));
thr.Start();
}
public static void MSGshow()
{
MessageBox.Show("Ran");
}
}
}
Upvotes: 0
Views: 2354
Reputation: 21709
A few things...
The DoWork
event is fired once to do the background work and must not do anything that accesses UI controls/UI thread.
There are two other events that you can use. ProgressChanged
is used to report progress. For example, you could implement that method to update a progress bar. The other one, and the one I think you should be interested in is RunWorkerCompleted
. In your case you'd have something like
bgwMessage.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(BgwFileOpen_ShowDialog);
...
private void BgwFileOpen_ShowDialog(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Ran");
}
Some other thoughts
Form
or other winforms class as BackgroundWorker
inherits from Component
.Dispose()
on the background worker.The BackgroundWorker Class documentation provides a great example of how to use the class properly.
If you must create and start the worker from Read()
, I suggest that you instead start a Thread
instead, and have it send a message to the UI thread when done. Your message handler would then fire up the message box.
You can even use a Task
, and then add a continuation to the task that continues on the UI thread, calling MessageBox.Show()
.
It appears that the Immmediate window may have issues executing threads or at least showing the outputs/results of other threads other than the one in which it is running. It's designed for interacting with you (the developer) more so than as a fully functional environment to run applications in, such as winforms.
I am confident that if you design your Read()
method to accept a background worker that is properly implemented (i.e. created and setup outside of Read()
), and then call RunWorkerAsync()
inside Read()
, the message box should pop up as expected -- just not that you'd see it when going via Immediate window.
Upvotes: 1
Reputation: 366
I would suggest using Tasks. It works with any dotnet above 4.5 (4.0 also with additional packages)
using System.Threading.Tasks;
public class ST
{
public static async Task Read()
{
await Task.Run(() => {
//Do some big work here
};
}
}
Then for example on your button click event just call:
private async void Button_Click(object sender, EventArgs e)
{
await ST.Read();
MessageBox.Show("Ran");
}
This will not freeze your view while you do that big Read task and will come back to the next line of the Button_Click function once it's done to show the dialog result.
You can even add some code before the Read call to warn the user that something is happening in the background :)
Upvotes: 1