Gui: need to serialize a sequence of BackgroundWorker calls - c#

I have a WPF app in which I've implemented some BackgroundWorker threads to update the Gui. Sometimes it works perfectly, other times I get variable out of range exceptions (when the same code is targeted by several threads simultaneously).
What is the simplest way to ensure I use ONE BackgroundWorker at a time to avoid these code clashes. In other words I want to make the BackgroundWorker calls sequential instead of paralell. I still want my GUI to be responsive. And the BackgroundWorker processes are fast enough that sequential speeds are adequate. I've attempted 'lock' and 'semaphore' but they don't seem to work with the BackgroundWorker constructs. Any quick fixes?

A global lock will prevent worker threads running concurrently. Having said that its not an approach I would choose. I'd rather use the Task Parallel Library for concurrent computations and Async for asynchronous IO. Here we go:
static object glock = new object();
private void button1_Click(object sender, EventArgs e)
{
using (BackgroundWorker w1 = new BackgroundWorker())
{
w1.DoWork += (s, we) =>
{
lock (glock)
{
//Some computation
we.Result = 1;
}
};
w1.RunWorkerAsync();
}
using (BackgroundWorker w2 = new BackgroundWorker())
{
w2.DoWork += (s, we) =>
{
lock (glock)
{
//Some computation
we.Result = 2;
}
};
w2.RunWorkerAsync();
}
}

Ok I discovered tasks and taskfactorys with continuations. That's a much more flexible solution for my current project than the background worker.
I'm using the synchronous option for continuations and its giving me the results I need.
Thanks for the help

Related

C# Is it safe to call 'BackgroundWorker' inside 'using' statement?

I have developed a windows service. In the service I was using a BackgroundWorker to Post data in my Database.
I declared a BackgroundWorker inside my database constructor class and was using that whenever needed.
During the test I got one error:
This BackgroundWorker is currently busy and cannot run multiple tasks
concurrently
I tried to find out the solution and many people suggest to use new instance for each task. I changed my code like:
...
using (BackgroundWorker bw = new BackgroundWorker())
{
bw.DoWork += new DoWorkEventHandler(bkDoPost);
bw.RunWorkerAsync(dbobj);
}
...
and my 'bkDoPost' is:
void bkDoPost(object sender, DoWorkEventArgs e)
{
try
{
dbObject dbj = e.Argument as dbObject;
this.db.Insert(dbj.tableName, dbj.data);
}
catch (Exception ex)
{
logs.logMessage("There was an error in data post. See the ErrorLog");
logs.logError(ex);
}
}
The code works fine during test.
My question is am I doing correct way?
OR Is there any issue doing in that way?
Thanks
Don't do that. Your background worker will be disposed before your work completes.
It is better to call Dispose manually after the work completes.
Better still, consider using a different scheme for handling asynchronous work. Background worker is becoming obsolete and is targeted at UI applications, rather than services. The restriction on parallel operations highlights the intention of the class.
Don't put the BackgroundWorker into a using statement. Instead put the Dispose() call into the RunWorkerCompleted event.
Nevertheless BackgroundWorker is maybe not the best thing to use in your case, cause it is primilary use is to run some buisness code while the UI stays responive and to automatically update the UI within the RunWorkerCompeleted event.
If you don't need to interfere with the UI when the job is finished or you have a lot of smaller jobs to be done it would be more efficient to switch to encapsulate your jobs within Tasks.
If you have many updates, creating one BackgroundWorker for each one could be very time and memory consuming.
I would use an independant thread that I would wake up each time an update has to be done :
Queue<DbWork> dbUpdates = new Queue<DbWork>();
EventWaitHandle waiter = new EventWaitHandle(false, EventResetMode.ManualReset);
...
// Init :
new Thread(new ThreadStart(DbUpdateWorker));
...
private void DbUpdateWorker()
{
while (true)
{
DbWork currentWork = null;
lock (dbUpdates)
{
if (dbUpdates.Count > 0)
currentWork = dbUpdates.Dequeue();
}
if (currentWork != null)
{
currentWork.DoWork();
}
if (dbUpdates.Count == 0)
{
waiter.WaitOne();
}
}
}
public void AddWork(DbWork work)
{
lock (dbUpdates)
{
dbUpdates.Enqueue(work);
}
waiter.Set();
}

c# application, Handles in task manager increase and system hanged

In our application we used Threads and Delegate to get the best performance. In order to gate our operations we use the System.Timers.Timer class.
When the application start , after 1 hour the task manager shows that the number of handles increased and cpu usage increases as well.
What can we do to dispose objects of Thread and delegate?
below code can help you to check this task.
public partial class Form1 : Form
{
System.Timers.Timer MainTimer;
public Form1()
{
InitializeComponent();
MainTimer = new System.Timers.Timer();
MainTimer.Elapsed+=new System.Timers.ElapsedEventHandler(MainTimer_Elapsed);
}
Thread MainThread;
private void button1_Click(object sender, EventArgs e)
{
MainTimer.Interval = 10;
MainTimer.Start();
}
void MainTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
MainThread = new Thread(new ThreadStart(DoStart));
MainThread.Start();
}
void DoStart()
{
PrintInfo();
}
delegate void PrintInfo_Delegate();
void PrintInfo()
{
if (textBox1.InvokeRequired)
{
Invoke(new PrintInfo_Delegate(PrintInfo));
}
else
{
textBox1.Text += "Test\r\n";
}
}
}
Apologies if I'm misparsing something, but it looks like once the button is clicked, you're then starting a new thread (in MainTimer_Elapsed) every 10 milliseconds? Without knowing more about the context / versions, it's hard to give specific advice on an alternative (async/await, TPL, etc), but off-hand it seems like anything creating new threads (especially non-background threads) like that is doing so unnessarily?
For processing non-UI work, perhaps use ThreadPool.QueueUserWorkItem instead of creating your own? For UI work, maybe use BackgroundWorker? If you're exhausting the thread pool, you could also consider setting things like max thread count, but using TPL and avoiding the use/creation/management of threads would be better/simpler IMHO if you're able to target .Net 4.x

Multiple background threads

I have one c# application that uses BackGroundWorker to do a group of tasks:
private void buttonStartCheckOut_Click(object sender, EventArgs e)
{
BackgroundWorker checkOuter = new BackgroundWorker();
checkOuter.DoWork += new DoWorkEventHandler(checkOuter_DoWork);
checkOuter.RunWorkerAsync();
checkOuter.RunWorkerCompleted += new RunWorkerCompletedEventHandler(checkOuter_RunWorkerCompleted);
}
void checkOuter_DoWork(object sender, DoWorkEventArgs e)
{
if (textBoxCICheckOut.Text != "")
CheckOutCI();
if (textBoxCACheckOut.Text != "")
CheckOutCA();
if (textBoxCAuthCheckOut.Text != "")
CheckOutCAuth();
if (textBoxCLCheckOut.Text != "")
CheckOutCL();
if (textBoxCCCheckOut.Text != "")
CheckOutCC();
}
As you can see, I have only 2 threads; one for GUI and one for secondary task.
Its easy for me to track when all the functions finish.
Now I want to make it more fast by creating a separate thread for CheckOutCI(), CheckOutCA() and others.Creating 5 background workers looks kinda dirty.
I want to ask:
How will I keep track of when all the functions have finished executing.
If any one function returned an exception, I want to display it to user and ask the user to correct the user and try again. I hope I am able to explain my question properly.
PLEASE edit the code by wdavo as per my comment on his post.
I'd look at using the Task library (Assuming you are running .NET 4.5 or later). I find it much better to use than background workers in most cases.
(Note you can still use the Task library in .NET 4, however Task.WhenAll is only available in 4.5)
http://msdn.microsoft.com/en-us/library/dd235618
Without rewriting your whole program, here's an example of how you would use it:
Move your simple conditional logic to the button
private void button1_Click(object sender, EventArgs e)
{
var tasks = new List<Task>();
if (Text == "A")
{
tasks.Add(funcA());
}
if (Text == "B")
{
tasks.Add(funcB());
}
//And so on....
Task.WhenAll(tasks.ToArray()).ContinueWith(t =>
{
if (t.Exception != null)
{
//One of the tasks threw an exception
MessageBox.Show("There was an exception!");
}
else
{
//None of the tasks threw an exception
MessageBox.Show("No Exceptions!");
}
});
}
We add the tasks to a collection so we can know when they all finish via Task.WhenAll. When all the tasks in the collection have finished, a message box will be displayed. If any of the tasks in the collection have thrown an exception, the Exception property of 't' will be populated. The specific exceptions exist as inner exceptions of this exception.
Move your threading code to individual task/functions. You'd create your checkout functions to look similar to this:
private Task funcA()
{
return Task.Factory.StartNew(() =>
{
try
{
//Code running here will be executed on another thread
//This is where you would put your time consuming work
//
//
}
catch(Exception ex)
{
//Handle any exception locally if needed
//If you do handle it locally, make sure you throw it again so we can see it in Task.WhenAll
throw ex;
}
//Do any required UI updates after the work
//We aren't on the UI thread, so you will need to use BeginInvoke
//'this' would be a reference to your form
this.BeginInvoke(new Action(() =>
{
//...
}));
});
}
What this does is the following
Creates a and runs a task which does some work on a thread from the thread pool
If there is an exception, we handle it locally .We re-throw the exception so that we can know that a task has failed when 'Task.WhenAll' is executed
Updates the UI after the work is done. You need to call BeginInvoke to run the code on the UI thread to avoid cross threading issues.
Starting up more threads than CPUs or cores can actually make your application slower. When there are more CPU-bound threads than CPUs the OS needs to context switch more often between the threads--which is hugely expensive and could result in the OS spending more time context switching between your threads than giving them time to work.
You can use the parallel aspect of the Parallel Task Library to automatically distribute your load across CPUs. For example:
Action[] actions = new Action[] {CheckOutCI, CheckOutCA, CheckOutCAuth, CheckOutCL, CheckOutCC};
Parallel.ForEach(actions, e=>e());
...which isn't exactly what you want; but should give you a general idea. e.g. populate actions based on current conditions.
You need to use ReportProgress method in backgroundworker
void checkOuter_DoWork(object sender, DoWorkEventArgs e)
{
if (textBoxCICheckOut.Text != "")
CheckOutCI();
checkOuter.ReportProgress(completionPercentage,"Error message");
The data sent in ReportProgress can be captured in checkOuter_ProgressChanged event
checkOuter_ProgressChanged(object sender,ProgressChangedEventArgs e)
{
int percentage = e.ProgressPercentage;
string message = e.UserState;
}

WPF / XAML: How do I execute threaded processes and prevent the main UI from being busy / freezing?

I have a XAML application that serves as the UI for an automation. The entire automation can take anywhere from 20-30 hours to fully execute so I created a Task class object that essentially wraps Thread methods (Start/Stop/Reset).
However, when I run the automation method under the Task object, the XAML UI is busy and I cannot interact with the other controls, including the Pause button which toggles the Thread.Set() flag.
There is another post
Prevent UI from freezing without additional threads
where someone recommended the BackgroundWorker class this MSDN article mentions it is a bad idea to use this when if it manipulates objects in the UI, which mine does for purposes of displaying status counts:
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Any idea around this?
private void OnButtonStartAutomationClick(object sender, RoutedEventArgs e)
{
btnPauseAutomation.IsEnabled = true;
Automation.Task AutomationThread = new Automation.Task(RunFullAutomation);
}
private void RunFullAutomation()
{
// do stuff that can take 20+ hours
// threaded so I can utilize a pause button (block)
}
class Task
{
private ManualResetEvent _shutdownFlag = new ManualResetEvent(false);
private ManualResetEvent _pauseFlag = new ManualResetEvent(true);
private Thread _thread;
private readonly Action _action;
public Task(Action action)
{
_action = action;
}
public void Start()
{
ThreadStart ts = new ThreadStart(DoDelegatedMethod);
_thread = new Thread(ts);
_thread.Start();
_thread.Priority = ThreadPriority.Lowest;
}
public void Resume()
{
_pauseFlag.Set();
}
public void Stop()
{
_shutdownFlag.Set();
_pauseFlag.Set();
_thread.Join();
}
private void DoDelegatedMethod()
{
do
{
_action();
}
while (!_shutdownFlag.WaitOne(0));
}
}
where someone recommended the BackgroundWorker class this MSDN article mentions it is a bad idea to use this when if it manipulates objects in the UI, which mine does for purposes of displaying status counts
BackgroundWorker is actually ideal for this, as it was designed for this type of scenario. The warning is that you shouldn't change UI elements inside of DoWork, but rather via ReportProgress and the ProgressChanged event.
The reason the warning exists is "DoWork" is executed on a background thread. If you set a UI element value from there, you'll get a cross threading exception. However, ReportProgress/ProgressChanged automatically marshals the call back into the proper SynchronizationContext for you.
Take a look at the Dispatcher object in WPF. You can, and should in your scenario, run the long running tasks on a background thread and the BackgroundWorker is a good way to do it. When you need to update the UI you need to verify access to the UI thread and if you don't have it use the dispatcher to invoke an update method on the UI thread.
There are two possible causes here: first, that the blocking task is blocking the UI thread rather than running on a background thread, and second, that the background thread is starving the UI thread so that it never gets the chance to respond to input. You need to find out which of these is the case. A crude way to do this is, in your Click handler, Debug.WriteLine the current thread ID (Thread.CurrentThread.ManagedThreadId), and do the same in the RunFullAutomation callback.
If these print the same number, then you have the first problem. Reed and TheZenker have provided solutions to this.
If these print different numbers, then you are already on a worker thread, and you have the second problem. (BackgroundWorker may get you to the worker thread more elegantly, and will help with updating the UI, but it won't stop starvation.) In this case the simplest fix is probably to set _thread.Priority = ThreadPriority.BelowNormal; before starting the worker thread.
By the way, your code never appears to actually call AutomationThread.Start, which means the RunFullAutomation callback isn't even executed. Is this just a typo?
I'd advise against rolling out your own Task class given that .NET 4 has full support for running tasks asynchronously in the background using the Task Parallel Library
That said,you can do what Reed suggests and use a BackgroundWorker which is ideal or if you prefer more control over the nature of how the task si executing, you could use the Task class from System.Threading.Tasks and implement something like so:
public partial class MainWindow : Window
{
CancellationTokenSource source = new CancellationTokenSource();
SynchronizationContext context = SynchronizationContext.Current;
Task task;
public MainWindow()
{
InitializeComponent();
}
private void DoWork()
{
for (int i = 0; i <= 100; i++)
{
Thread.Sleep(500); //simulate long running task
if (source.IsCancellationRequested)
{
context.Send((_) => labelPrg.Content = "Cancelled!!!", null);
break;
}
context.Send((_) => labelPrg.Content = prg.Value = prg.Value + 1, null);
}
}
private void Start_Click(object sender, RoutedEventArgs e)
{
task = Task.Factory.StartNew(DoWork, source.Token);
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
source.Cancel();
}
}
In DoWork() you use the WPF SynchronizationContext and post messages to update the UI wiget you need.
The example has a progress bar and a label control that is updated on each iteration of the for loop.Cancellation is supported using CancellationTokenSource which is checked in each iteration.
Hope this helps.

What's a useful pattern for waiting for all threads to finish?

I have a scenario where I will have to kick off a ton of threads (possibly up to a 100), then wait for them to finish, then perform a task (on yet another thread).
What is an accepted pattern for doing this type of work? Is it simply .Join? Or is there a higher level of abstraction nowadays?
Using .NET 2.0 with VS2008.
In .NET 3.5sp1 or .NET 4, the TPL would make this much easier. However, I'll tailor this to .NET 2 features only.
There are a couple of options. Using Thread.Join is perfectly acceptable, especially if the threads are all ones you are creating manually. This is very easy, reliable, and simple to implement. It would probably be my choice.
However, the other option would be to create a counter for the total amount of work, and to use a reset event when the counter reaches zero. For example:
class MyClass {
int workToComplete; // Total number of elements
ManualResetEvent mre; // For waiting
void StartThreads()
{
this.workToComplete = 100;
mre = new ManualResetEvent(false);
int total = workToComplete;
for(int i=0;i<total;++i)
{
Thread thread = new Thread( new ThreadStart(this.ThreadFunction) );
thread.Start(); // Kick off the thread
}
mre.WaitOne(); // Will block until all work is done
}
void ThreadFunction()
{
// Do your work
if (Interlocked.Decrement(ref this.workToComplete) == 0)
this.mre.Set(); // Allow the main thread to continue here...
}
}
Did you look at ThreadPool? Looks like here -ThreadPool tutorial, avtor solves same task as you ask.
What's worked well for me is to store each thread's ManagedThreadId in a dictionary as I launch it, and then have each thread pass its id back through a callback method when it completes. The callback method deletes the id from the dictionary and checks the dictionary's Count property; when it's zero you're done. Be sure to lock around the dictionary both for adding to and deleting from it.
I am not sure that any kind of standard thread locking or synchronization mechanisms will really work with so many threads. However, this might be a scenario where some basic messaging might be an ideal solution to the problem.
Rather than using Thread.Join, which will block (and could be very difficult to manage with so many threads), you might try setting up one more thread that aggregates completion messages from your worker threads. When the aggregator has received all expected messages, it completes. You could then use a single WaitHandle between the aggregator and your main application thread to signal that all of your worker threads are done.
public class WorkerAggregator
{
public WorkerAggregator(WaitHandle completionEvent)
{
m_completionEvent = completionEvent;
m_workers = new Dictionary<int, Thread>();
}
private readonly WaitHandle m_completionEvent;
private readonly Dictionary<int, Thread> m_workers;
public void StartWorker(Action worker)
{
var thread = new Thread(d =>
{
worker();
notifyComplete(thread.ManagedThreadID);
}
);
lock (m_workers)
{
m_workers.Add(thread.ManagedThreadID, thread);
}
thread.Start();
}
private void notifyComplete(int threadID)
{
bool done = false;
lock (m_workers)
{
m_workers.Remove(threadID);
done = m_workers.Count == 0;
}
if (done) m_completionEvent.Set();
}
}
Note, I have not tested the code above, so it might not be 100% correct. However I hope it illustrates the concept enough to be useful.

Categories