BackgroundWorker used within collection items - c#

I used a Backgroudworker to do some work in order to do some time consuming tasks.
public void ConnectDataProvider()
{
bgw = new BackgroundWorker();
bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
}
Another method starts the background worker:
public void StartPolling()
{
bgw.RunWorkerAsync();
}
Then I did the event handling:
void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// do it over again
StartPolling();
}
void bgw_DoWork(object sender, DoWorkEventArgs e)
{
// do work
WriteData();
}
As you can see, I started the worker over on completion. Now this works for a single backgroundworker.
Now I want a collection, and each item should perform this task. However with the concept above it will just keep on running in the first worker started, as it starts the worker over. I'm thinking, maybe a Timer in combination could solve the situation to give the other worker threads way.
Is the BackgroundWorker still a good choice? Is it common to reuse the BackgroundWorker like I did?
EDIT 1: To clairify: The problem I'm facing is, that I need manage the collection each with their own BackgroundWorker. I was thinking about a timer, to set off request periodically from each item. This is where I'm stuck.
EDIT 2: See my own answer, I didn't solve this issue, but found that I can go along with timers to get what I wanted.
EDIT 3: To clarify (another try, I'm not good at that) what I wanted to achieve: I've got tracking objects, for gps tracking. I want to track a whole bunch of them, so one object per tracking device. They all need to be polled frequently. Ihad a BackgroundWorker set up for a single test object. I liked they way the Backgroundworker would tell me when it's done. But I couldn't get it working with all of the tracking objects.
Now every tracking object has its own timer. This timer spawns a new thread and does the time consuming work (which I named DoWrite). No BackgroundWorker needed, as I dispose the timer and then create a new timer. That's all it does.

How many of these might there be? You should be careful of creating a 1:1 relationship between items in a collection and threads. Another coder might come along and expand this collection more than you planned.
For things like this I usually like to use just the one thread, and a queue - so the events just put the work that needs to be done in a ConcurrentQueue, and the thread starts if not running, and churns through the queued work until it's out of things to do, and dies. The next time more work comes in the event will check if the thread is running and start it.
It's cheaper because if there's a lot going on, you run just the one thread instead of stopping and starting a lot of them, or if there's very little going on, the one thread is almost never running.

Your solution would look more logical if you just put a while() loop in Dowork(), maybe with a little Sleep().
And then there would be no objection against running multiple Bgw's, although you may not see a great speed benefit.

You can do exactly what you describe--just make sure that you pass the reference to the relevant background worker to StartPolling, thusly:
void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// do it over again
StartPolling((BackgroundWorker)sender);
}
public void StartPolling(BackgroundWorker worker)
{
worker.RunWorkerAsync();
}
Then obviously, you need to manage the collection of BackgroundWorker's accordingly.

Why don't you use the progresschanged event? You could use the userstate object for passing data.
In do work just pool the devices, and in process changed send the data to the UI thread.
Do it in a endless while and use cancel to stop that thread.
Regards.

When you have multiple time consuming tasks to be executed in the same time, I suggest you to use Thread Pool
http://msdn.microsoft.com/en-us/library/ms973903.aspx

Since nobody did it so far, I'll throw in the timer approach. I tried to combine the two (BackgroundWorker and Timer), but that didn't make sense.
I wanted a mechanism to allow multiple instances to request data by thread. Also, I wanted some interval in between.
So after trying around, I figured I could get along with a Timer-approach only:
public void ConnectDataProvider()
{
timer = new Timer(new TimerCallback(tCallback), null, 0, Timeout.Infinite);
}
private void tCallback(object state)
{
timer.Dispose();
// time consuming task
WriteData();
timer = new Timer(new TimerCallback(tCallback), null, 5000, Timeout.Infinite);
}
That was what John Saunders suggested on a similar (but different) problem. It seems to do the job. The WriteData() has a synchronous HttpWebRequest, so it can handle a timeout.
My question now is: How expensive is the new instantiation of the timer object? By how expensive I mean: Are there better ways to achieve that?
Note: The asynchronous approach of the WebRequest won't work, I tried that. I have no clue so far, if that is a manner of the server.

Related

Best practice for an endless/ periodic execution of code in C#

Often in my code I start threads which basically look like this:
void WatchForSomething()
{
while(true)
{
if(SomeCondition)
{
//Raise Event to handle Condition
OnSomeCondition();
}
Sleep(100);
}
}
just to know if some condition is true or not (for example if a have a bad coded library with no events, just boolean variables and I need a "live-view" of them).
I wonder if there is a better way to accomplish this kind of work like a Windows function to hook in which can run my methods all x sec. Or should I code a global event for my app, raising all x secs and let him call my methods like this:
//Event from Windows or selfmade
TicEvent += new TicEventHandler(WatchForSomething));
and then this method:
void WatchForSomething()
{
if(SomeCondition)
{
//Raise Event to handle Condition
OnSomeCondition();
}
}
So, I hope this is not closed because of being a "subjective question" or something, I just want to know what the best practice for this kind of work is.
There isn't necessarily a "best way" to write long-running event processing code. It depends on what kind of application you are developing.
The first example you show is the idiomatic way in which you would often see the main method of a long-running thread written. While it's generally desirable to use a mutex or waitable event synchronization primitive rather than a call to Sleep() - it is otherwise a typical pattern used to implement event processing loops. The benefit of this approach is that it allows specialized processing to run on a separate thread - allowing your application's main thread to perform other tasks or remain responsive to user input. The downside of this approach is that it may require the use of memory barriers (such as locks) to ensure that shared resources are not corrupted. It also makes it more difficult to update your UI, since you must generally marshal such calls back to the UI thread.
The second approach is often used as well - particularly in systems that already have an event-drive API such as WinForms, WPF, or Silverlight. Using a timer object or Idle event is the typical manner in which periodic background checks can be made if there is no user-initiated event that triggers your processing. The benefit here is that it's easy to interact and update user interface objects (since they are directly accessible from the same thread) and it's mitigates the need for locks and mutexes to protected data. One potential downside of this approach is if the processing that must be performed is time-consuming it can make your application unresponsive to user input.
If you are not writing applications that have a user interface (such as services) then the first form is used much more often.
As an aside ... when possible, it's better to use a synchronization object like an EventWaitHandle or Semaphore to signal when work is available to be processed. This allows you to avoid using Thread.Sleep and/or Timer objects. It reduces the average latency between when work is available to be performed and when event processing code is triggered, and it minimizes the overhead of using background threads, since they can be more efficiently scheduled by the runtime environment and won't consume any CPU cycles until there's work to do.
It's also worth mentioning that if the processing you do is in response to communications with external sources (MessageQueues, HTTP, TCP, etc) you can use technologies like WCF to provide the skeleton of your event handling code. WCF provides base classes that make it substantially easier to implement both Client and Server systems that asynchronously respond to communication event activity.
If you have a look at Reactive Extensions, it provides an elegant way of doing this using the observable pattern.
var timer = Observable.Interval(TimeSpan.FromMilliseconds(100));
timer.Subscribe(tick => OnSomeCondition());
A nice thing about observables is the ability to compose and combine further observables from existing ones, and even use LINQ expressions to create new ones. For example, if you wanted to have a second timer that was in sync with the first, but only triggering every 1 second, you could say
var seconds = from tick in timer where tick % 10 == 0 select tick;
seconds.Subscribe(tick => OnSomeOtherCondition());
By the way, Thread.Sleep is probably never a good idea.
A basic problem with Thread.Sleep that people are usually not aware of, is that the internal implementation of Thread.Sleep does not pump STA messages. The best and easiest alternative, if you have to wait a given time and can't use a kernel sync object, is to replace Thread.Sleep with Thread.Join on the current thread, with the wanted timeout. Thread.Join will behave the same, i.e. the thread would wait the wanted time, but in the meantime STA objects will be pumped.
Why this is important (some detailed explanatiopn follows)?
Sometimes, without you even knowing, one of your threads may have created an STA COM object. (For example this sometimes happens behind the scenes when you use Shell APIs). Now suppose a thread of yours has created an STA COM object, and is now in a call to Thread.Sleep.
If at sometime the COM object has to be deleted (which can happen at an unexpected time by the GC), then the Finalizer thread will try calling the object's distruvtor. This call will be marshalled to the object's STA thread, which will be blocked.
Now, in fact, you will have a blocked Finalizer thread. In this situations objects can't be freed from memory, and bad things will follow.
So the bottom line: Thread.Sleep=bad. Thread.Join=reasonable alternative.
The first example you show is a rather inelegant way to implement a periodic timer. .NET has a number of timer objects that make this kind of thing almost trivial. Look into System.Windows.Forms.Timer, System.Timers.Timer and System.Threading.Timer.
For example, here's how you'd use a System.Threading.Timer to replace your first example:
System.Threading.Timer MyTimer = new System.Threading.Timer(CheckCondition, null, 100, 100);
void CheckCondition(object state)
{
if (SomeCondition())
{
OnSomeCondition();
}
}
That code will call CheckCondition every 100 milliseconds (or thereabouts).
You don't provide a lot of background on why you're doing this, or what you're trying to accomplish, but if its possible, you might want to look into creating a windows service.
Use a BackgroundWoker for additional thread safe measures:
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.WorkerReportsProgress = true;
.
.
.
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (;;)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(100);
}
}
}
For more info visit: http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx
A very simple way for non blocking wait other threads/tasks is:
(new ManualResetEvent(false)).WaitOne(500); //Waits 500ms

How to start a thread to keep GUI refreshed?

I have window with button which triggers lengthy processing. I put processing in a separate thread, but -- to my surprise -- it makes GUI frozen anyway. No control is refreshed, I cannot even move the window.
So the question is how to start the thread, so it won't interfere with GUI, i.e. so the GUI would always be up to date (while processing I change the data, and GUI displays some pieces of it)?
That is how I start thread currectly:
var thread = new Thread(doLearn);
thread.IsBackground = true;
thread.Start();
Edit 1
Jon:
I don't use any locks at all
No Join calling
The UI thread is left alone -- it simply sits there
The processing is a big loop with math operations, not even allocating memory, on UI side I have controls with binding (WPF) to data, like the number of current iteration of the main loop. It should be refreshed each time the main loop "ticks". The counter of the loop is a property which triggers OnPropertyChanged with each change (classic WPF binding).
Edit 2 -- Almost there!
Ok, so Jon hit the nail at the head (who is surprises? ;-D) -- thank you! The problem comes from changing the Counter. When I used instead the Counter, local counter the GUI was refreshed -- I mean I could move windows, but... I couldn't see display of the Counter.
What I have here -- a WPF GUI, with such data-binding
<TextBlock Text="{Binding Path=Counter"/>
and I have Counter property of course which on each change sends event PropertyChanged. One of the listeners is for sure GUI.
So, Jon answer is valid "the answer", but from good design POV not exactly, because if GUI part has to pull up the info about Counter and update the display every (let's say) 3 seconds, why would anyone use data binding? For me such approach invalidates data binding idea.
I could, theoretically, pass to the processing thread the GUI dispatcher, and do all the sending in GUI thread, and it could work (I didn't try it) but it would mean tight coupling of non-GUI part and GUI part.
So far, I have no idea how to do it "right" way. The best guess so far is to create TimerDispatcher but not at GUI side but inside the processing library, and update Counter value immediately but do all the sending from time to time (I didn't try it yet though).
Small remark: I have more properties binded actually, like IsRunning, which is changed at the beginning and at the end of processing. And those changes DO affect the display correctly -- but the Counter change triggers around 3000 notifications in 3-4 seconds. So it looks like jamming problem. I did another test -- I killed the data binding partially, so notifications were sent, but GUI was not "receiving" them -- but was listening to them. In such case the GUI was also frozen.
So, I am still listening to all advices -- thank you advance for sharing.
Edit 3
The saga continues here:
How to do the processing and keep GUI refreshed using databinding?
It should be fine as it is. Things which may be freezing your UI:
Are you locking within the UI thread, and locking on the same lock in your other thread?
Are you calling Join on the thread from your UI thread?
Are you doing some other heavy work in the UI thread?
If you could come up with a short but complete program which shows the problem, I'm sure we could help to fix it... but it certainly should be okay.
EDIT: Okay, now you've added this:
The counter of the loop is a property which triggers OnPropertyChanged with each change (classic WPF binding).
So you're updating the property from the non-UI thread? I would expect that to cause problems, because it will trigger UI changes from the wrong thread.
I suggest you take an approach such as:
Periodically update the counter via Dispatcher.BeginInvoke
Have the "UI counter" and the "worker counter" - and copy the value from the "worker counter" to the "UI counter" in the UI thread via a DispatcherTimer, essentially polling it.
There are numerous methods to run functions off the UI thread, but the easiest and generally most suitable is to look at the BackgroundWorker component. Many decent tutorials can be found. For example, here.
I put processing in a separate
thread, but -- to my surprise -- it
makes GUI frozen anyway.
I really hate to tell you, but then you did NOT put it into a separate thread. That simlpe.
There was a poster here that had a similar issue some time ago and through a mistake in his invoking code he basically had all processing before the thread started, with the thread jsut returning the result.
I faced the same situation, and solved it by two ways...
Use the thread in other class and invoke it in ur main application by creating Thread, either in its constructor OR in any method.
if u want do the it in same class, then create a Thread that call your function, and that function should invoke the Delegate.
See the examples:
public partial class Form1 : Form
{
private delegate void TickerDelegate();
TickerDelegate tickerDelegate1;
public Form1()
{
InitializeComponent();
}
//first solution
// This button event call other class having Thread
private void button1_Click(object sender, EventArgs e)
{
f = new FormFileUpdate("Auto File Updater", this);
f.Visible = true;
this.Visible = false;
}
// Second Solution
private void BtnWatch_Click(object sender, EventArgs e)
{
tickerDelegate1 = new TickerDelegate(SetLeftTicker);
Thread th = new Thread(new ThreadStart(DigitalTimer));
th.IsBackground = true;
th.Start();
}
private void SetLeftTicker()
{
label2.Text=DateTime.Now.ToLongTimeString();
}
public void DigitalTimer()
{
while (true)
{
label2.BeginInvoke(tickerDelegate1, new object[] {});
Thread.Sleep(1000);
}
}
}

form update too expensive to be executed in Winform.Timer.Tick

I have a WinForm drawing a chart from available data.
I programmed it so that every 1 secong the Winform.Timer.Tick event calls a function that:
will dequeue all data available
will add new points on the chart
Right now data to be plotted is really huge and it takes a lot of time to be executed so to update my form. Also Winform.Timer.Tick relies on WM_TIMER , so it executes in the same thread of the Form.
Theses 2 things are making my form very UNresponsive.
What can I do to solve this issue?
I thought the following:
moving away from usage of Winform.Timer and start using a System.Threading.Timer
use the IsInvokeRequired pattern so I will rely on the .NET ThreadPool.
Since I have lots of data, is this a good idea?
I have fear that at some point also the ThreadPool will be too long or too big.
Can you give me your suggestion about my issue?
Thank you very much!
AFG
It is a good idea to move the fetching of the data to a Thread. You can use a BackgroundWorker that gets the data in an endless loop and
use the UpdateProgress event to update the chart. This takes care of the InvokeRequired business
Use a Sleep(remainingTime) inside the loop to get a desired frequency.
It is quite unlikely you'll be ahead by using a background timer. Your chart control almost certainly requires it to be updated from the same thread is was created on. Any kind of control that has a visible appearance does. Which requires you to use Control.BeginInvoke in the Elapsed event handler so that the update code runs on the UI thread. Dequeueing data isn't likely to be expensive, you will have actually have made it slower by invoking. And still not have taken the pressure off the UI thread.
You'll also have a potentially serious throttling problem, the timer will keep on ticking and pump data, even if the UI thread can't keep up. That will eventually crash your program with OOM.
Consider instead to make the code that updates the chart smarter. A chart can only display details of the data if such details are at least a pixel wide. Realistically, it can only display 2000 pixels with useful information. That's not much, updating 2000 data points shouldn't cause any trouble.
I would go with a System.Timers.Timer over a BackgroudWorker in an endless loop.
The BackgroundWorker is executed from a ThreadPool and is not meant to run for the lifetime of your application.
Motivation for System.Timers.Timer:
Each elapsed event is executed from a ThreadPool, won't hang your UI thread.
Using a combination of locks and enabling/disabling the timer we can get the same frequency as if we did a Thread.Sleep(xxx) in an endless loop.
Cleaner and more obvious as to what you are trying to achieve
Here's my suggestion:
Disabling the timer at the beginning of the method, then re-enabling it again at the end, will cater for the case where the amount of work done in the elapsed event takes longer than the timer interval. This also ensures the timer between updates is consistent. I've added a lock for extra precaution.
I used an anonymous method to update the UI thread, but you can abviously do that however you want, as long as you remember to Invoke, it's also a good idea to check the InvokeRequired property
private readonly object chartUpdatingLock = new object();
private void UpdateChartTimerElapsed(object sender, ElapsedEventArgs e)
{
// Try and get a lock, this will cater for the case where two or more events fire
// in quick succession.
if (Monitor.TryEnter(chartUpdatingLock)
{
this.updateChartTimer.Enabled = false;
try
{
// Dequeuing and whatever other work here..
// Invoke the UI thread to update the control
this.myChartControl.Invoke(new MethodInvoker(delegate
{
// Do you UI work here
}));
}
finally
{
this.updateChartTimer.Enabled = true;
Monitor.Exit(chartUpdatingLock);
}
}
}

Listbox not completely vanishing on hide

I've got a simple method that does this:
private void searchButton_Click(object sender, EventArgs e)
{
searchResultsBox.Hide();
doSomething();
}
searchResultsBox is a listbox, and when I call its Hide method, it doesn't actually completely vanish until 'doSomething' finishes processing. It kind of leaves artifacts (in fact you can still see any part of the box that had an empty form surface behind it.
If I comment out 'doSomething', it vanishes promptly.
Any ideas on how to fix this? It's just a bit ugly.
You could try calling this.refresh() after calling searchResultsBox.Hide();
You should not do significant work in the GUI event thread, as it will cause the UI to freeze up while it is busy running your event handling code. It is a good practice to do any long-running tasks in another thread, either by signaling another already-running thread to do the work or by starting a new thread on the spot.
new Thread(new ThreadStart(doSomething)).Start();
Sound like doSomething is process intensive and blocking the GUI thread, not sure why it would not finishing hiding the list before executing doSomething.
I would try putting doSomething in to a separate thread.
The separate thread or background worker process is the best answer. You can also try calling Application.DoEvents(). That seems to work at times for this specific issue although I'm not in favor of using that call often.

Using threads to count the loops in C# events

EDIT: It is not a listbox. My mistake. It is a list view.
I have a list view control that's driving me nuts. It is a multi-select list box, so if the user selects 5000 rows, then de-selects them by selecting a single row, the SelectedIndexChanged fires 5001 times. This causes my app to hang.
I'm trying to use threads to count the number of times that the event WOULD have fired, and then letting the last iteration do all the actual work.
Here's the code I started with. The big catch: I need the "do fancy calculations" to be in the same thread as the calling events due to items out of my control.
EDIT: I know that this code doesn't work. The Join() blocks the current thread which negates the entire purpose of creating the thread. My question is : How do I do something LIKE this.
My biggest problem isn't creating the thread. It's that my "do fancy" has to be in the same thread.
void IncrPaintQueue()
{
PaintQueue++;
Thread.Sleep(100);
}
int PaintQueue = 0;
private void SegmentList_SelectedIndexChanged(object sender, EventArgs e)
{
// We need to know how many threads this may possibly spawn.
int MyQueue = PaintQueue;
// Start a thread to increment the counter.
Thread Th = new Thread(IncrPaintQueue);
Th.IsBackground = true;
Th.Start();
Th.Join();
// if I'm not the last thread, then just exit.
// The last thread will do the right calculations.
if (MyQueue != PaintQueue - 1)
return;
// Reset the PaintQueue counter.
PaintQueue = 0;
// ... do fancy calculations here...
}
I remember solving this issue before:
A better way perhaps for you would be
to put a minimal delay in your
ItemSelectionChange Handler. Say --
50ms. Use a timer, Once the selection
changes, restart the timer. If the
selection changed more than once
within the delay period, then the
original is ignored, but after the
delay has expired, the logic is
executed.
Like this:
public class SelectionEndListView : ListView
{
private System.Windows.Forms.Timer m_timer;
private const int SELECTION_DELAY = 50;
public SelectionEndListView()
{
m_timer = new Timer();
m_timer.Interval = SELECTION_DELAY;
m_timer.Tick += new EventHandler(m_timer_Tick);
}
protected override void OnSelectedIndexChanged(EventArgs e)
{
base.OnSelectedIndexChanged(e);
// restart delay timer
m_timer.Stop();
m_timer.Start();
}
private void m_timer_Tick(object sender, EventArgs e)
{
m_timer.Stop();
// Perform selection end logic.
Console.WriteLine("Selection Has Ended");
}
}
A possible solution is to delay the work, so you know whether or not more events have fired. This assumes the order of the selections is not important; all that matters is the current state.
Instead of doing the work as soon as the event fires, set up a timer to do it a couple milliseconds after the event fires. If the timer is already running, do nothing. In this way the user should perceive no difference, but the actions will not hang.
You could also do the work on another thread, but have a flag to indicate work is being done. If, when the selection event fires, work is still being done you set a flag that indicates the work should be repeated. Setting 'repeat_work' to true 5000 times is not expensive.
I get the impression that you're trying to solve a problem through brute force. I would suggest trying a different event:
private void myListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (e.IsSelected)
{
// do your logic here
}
}
I would suggest avoiding creating threads if at all possible, since they have overheaad. I couldn't see from your example where there's any need for parallelism.
First, while you are properly synchronizing access to PaintQueue, I feel it was more by chance in this situation as opposed to design. If you have other code accessing PaintQueue on other threads, then you have a problem.
Second, this code makes no sense. You are spooling up a new thread, incrementing the value on that thread, and then waiting for 1/10th of a second. The thing is, the code that kicks off the thread is waiting on that thread to complete. Because of this, you are just waiting in the UI thread for nothing.
Even if you queue the SelectedIndexChange events, you aren't going to be able to prevent your app from hanging. The SelectedIndexChange event is going to fire every time that you select an item, and if the user selects 5000 items, then you need to process all 5000 events. You could give them a window (process every n seconds or whatever) but that's rather arbitrary and you put the user on a timer, which is bad.
What you should do is not tie the operation to the SelectedIndexChanged event. Rather, have the user select the items and then have them perform some other action (click a button, for example) which will work on the selected items.
Your app will still hang though if you have to process a number of items for a lengthy period of time on the UI thread, but at least selecting the items won't hang.
You don't really achieve any kind of concurrency by starting a new thread and then immediately Joining it. The only "effect" of the code above is that you method is run by another thread.
Additionally, if you want to use a background thread and safe the rather expensive cost of newing a thread, you should employ the thread pool.

Categories