Questions and Answers on any aspect of .NET. Now closed.
I have a situation where I have a process running in the background (reasonably heavy duty) and I am trying to show the information it is collecting on the screen. Right now I was attempting to have the control refresh itself (it listens for an event that is raised by the process when information is ready) when there is new information. This information is large though, could be 100-1000s of entries. I also tried having the refresh only happen every so often (as in, when new information is available, it starts a timer, when the timer expires the control refreshes itself) with no success.
Is there some paradigm for doing this sort of thing that I don't know about? Any resources? Thanks in advance.
Thursday, July 20, 2006
First question is what is actually happening when you try to refresh? Does the gui appear to hang or behave strangely.
The reason I ask this is, if the "background process" is running on another thread then trying to update the gui from that thread is a no go.
You would also see this behaviour depending on the type of timer you are using. If it is a system.timers.timer rather than the normal forms timer, then it runs on a seperate thread to the gui.
If either of the above is true then you have to marshall the gui update calls back onto your main gui thread. Let us know if this is the case.
Friday, July 21, 2006
The GUI and the background are on different threads. When the background does something, it writes to the database. Part of writing to the database raises an event, noting that the data has changed. The relevant controls are listening for that event and appear to try to refresh themselves. However, because the background is fast acting, it is producing data changes way faster than the GUI can consume them, so I am constantly reloading the controls.
I am also running into the issue that the database is slow and is slowing down the UI. I am not really in the mood to tear out the database and put in another, but I am not entirely opposed to the idea.
I am just wondering if there is some sort of paradigm that I don't know about to do this kind of process/GUI interaction. I can't be the first person to have this problem.
I suppose I should supply some relevant information. The GUI is written in C#, the database is access. It's a small application for a single user (no networking). To delay the raising of the event that causes the controls to reload, I was using the System.Threading.Timer.
> However, because the background is fast acting, it is producing data changes way faster than the GUI can consume them, so I am constantly reloading the controls.
If you're getting more than e.g. one event per second, then perhaps discard (ignore) the extra events and refresh the whole GUI no more than once per second.
I solved a similar problem a few years back in a heavily multithreaded app using a queue. Each 'data' thread would lock the queue, add its data element(s) and unlock the queue. The GUI thread would respond to a timer. When the timer went off the GUI thread would lock the queue, read the top N elements from the queue, remove them and unlock the queue. Since the queue was in memory there was no GUI performance degradation. In my case I adjusted 'N' on the fly based on the size of the queue (E.G. XX percent of queue size). If each data item has a unique ID in the DB and this is persisted through the queue to the GUI then the app state can be reconstructed in the event of a crash of the queue (or the app).
Hope this helps.
Friday, July 21, 2006
The simple answer is to change the type of timer you are using to the windows.forms.timer (something like that anyway) the one you are currently using executes on a seperate thread and therefore you cannot update your controls from it when it fires (unless you marshall back to your main thread)
Use the forms timer and it should work.
Friday, July 21, 2006
> Part of writing to the database raises an event,
> noting that the data has changed.
This is generally a bad idea and is a good example of a database shouldn't host application logic.
There are no rate controls on the event stream so you can swamp every part of the system in a hearbeat.
Instead, the events should go to an application and the written to the database. The application can keep a circular queue of N entries and you can poll for the entries you don't have using a sequence number. Or you can just get summaries of data, like averages or totals. Most people don't need to see raw data.
If you go beyond the N enries then go to the database and use normal paging logic. Perhaps using a read-only database if the other database has a lot of transactional action.
son of parnas
Friday, July 21, 2006
son of parnas,
The database isn't the thing actually raising the event. Whe it the application writes to the db, it alerts things that there is an update via an event. Although, you are right that the event stream has no throttling.
I do think that most people are talking about creating some sort of caching mechanism and then polling that, which I will try either this evening or tomorrow.
Does anyone know of a good example of this sort of code?
The suggestion that some other people have made regarding the use of Queues is fairly spot on as i had a similar problem to what your describing when getting the application to poll a database. Tables would lock up. Application would crawl. It was a real pain until i moved on to using message queues. Heres some very rough pseudo code that i used to solve my problem.
/* Background Process */
public void some_looping_function
//do some heavy processing
//perform some calculations
//push updates to an MSMQ
/* Foreground Application thread */
public static void main()
//place code in your main application to asynchronously
//connect to your message queue, and receive updates
//You can throttle this in your background thread, by
//putting some timespan logic in to only update the
//messages queues every 60 seconds, even if the
//database is being updated many times per second.
This means that your foreground app never actually has to touch the database, it just sits and waits to be told that new information is available and handles it when its given.
If your background thread is actually part of the same application, then you probably don't need to push the data out to a message queue. you could handle it internally using the System.Collections.Queue collection.
This topic is archived. No further replies will be accepted.Other recent topics
Powered by FogBugz