i have a database. imagine that my database have 1.000.000.000 records or includes 100 gb datas. i want to write a program.
the program basically will send a query to database to take 10 records and will display this records on the screen. then the user will use scroll bar on the mause to change the records displayed. for example when user scrolled down program will display records between 2 and 11. if the user keep scrolling down, the records keep displaying like between 3 and 12, 4 and 13 ... also the user can scroll up.
how can i use threads in a program like that. can anyone give a general idea for it. also if i want to use a pattern, which pattern can i use and why?
note: i can also use two buttons (for up and down) instead of scroll bar.
A typical pattern would be to have one thread handle the UI. Mouse, windowing, drawing, etc.
A worker thread would be created that did the actual DB i/o. That thread would collect responses from the database & place them in a buffer (or send them piecemeal) to the UI thread, which would then display them as they came in. Alternately, you could have the UI thread query the worker for a given range of records as the user works with the UI and this would require a way for the worker to respond immediately even if it didn't have all of the needed data.
At any rate, keeping the UI responsive while the work is executed is a typical pattern.
At the DB level itself, there are many ways to break down the execution of the search within the records into multiple parallel tasks (running on independent threads or fibers) doing the actual search requested from your program.
See allso for Model View Controller (MVC), Model View Presenter (MVP) and Model View ViewModel (MVVM) patterns to seperate the visualisation, business logic and data layers.
Related
Over 2 years ago, Remy Lebeau gave me invaluable tips on threads in Delphi. His answers were very useful to me and I feel like I made great progress thanks to him. This post can be found here.
Today, I now face a "conceptual problem" about threads. This is not really about code, this is about the approach one should choose for a certain problem. I know we are not supposed to ask for personal opinions, I am merely asking if, on a technical point a view, one of these approach must be avoided or if they are both viable.
My application has a list of unique product numbers (named SKU) in a database. Querying an API with theses SKUS, I get back a JSON file containing details about these products. This JSON file is processed and results are displayed on screen, and saved in database. So, at one step, a download process is involved and it is executed in a worker thread.
I see two different approaches possible for this whole procedure :
When the user clicks on the start button, a query is fired, building a list of SKUs based on the user criteria. A Tstringlist is then built and, for each element of the list, a thread is launched, downloads the JSON, sends back the result to the main thread and terminates.
This can be pictured like this :
When the user clicks on the start button, a query is fired, building a list of SKUs based on the user criteria. Instead of sending SKU numbers one after another to the worker thread, the whole list is sent, and the worker thread iterates through the list, sending back results for displaying and saving to the main thread (via a synchronize event). So we only have one worker thread working the whole list before terminating.
This can be pictured like this :
I have coded these two different approaches and they both work... with each their downsides that I have experienced.
I am not a professional developer, this is a hobby and, before working my way further down a path or another for "polishing", I would like to know if, on a technical point of view and according to your knowledge and experience, one of the approaches I depicted should be avoided and why.
Thanks for your time
Mathias
Another thing to consider in this case is latency to your API that is producing the JSON. For example, if it takes 30 msec to go back and forth to the server, and 0.01 msec to create the JSON on the server, then querying a single JSON record per request, even if each request is in a different thread, does not make much sense. In that case, it would make sense to do fewer requests to the server, returning more data on each request, and partition the results up among different threads.
The other thing is that threads are not a solution to every problem. I would question why you need to break each sku into a single thread. how long is each individual thread running and how much processing is each thread doing? In general, creating lots of threads, for each thread to work for a fraction of a msec does not make sense. You want the threads to be alive for as long as possible, processing as much data as they can for the job. You don't want the computer to be using as much time creating/destroying threads as actually doing useful work.
Right now my FMX project is totally based on Livebinding to connect the datasources to my editors on the form.
It works nice, besides to be slow and do not use paging loading (TLisView).
However, I have many different datasources and the amount of data can be huge and connections eventually slow.
My idea is to keep the user interface responsive and let threads in the background make the data load opening the datasources and put them it the right state. After that assigning the datasource to the controls on the form.
I have played with that with LiveBinding but I cannot mix the main thread with background ones. Some problems happened.
Having to load each field record to each control manually seems to be extremely unproductive. I have almost all the controls that I use already wrapped, I made my own controls based on the FMX ones, so I can have the possibility to add more functions.
I was wondering if there is something already done. Any class or library that I could use to map the source and targets and that I can have the control to activate when it is needed, since I can have many datasources in loading state by a thread.
This is not really a livebinding question.
Also without livebindings, when you retrieve data in a thread you have to respect the thread context. When getting a dataset from a connection, this dataset is also bound to that connection and the connection is bound to the thread context.
The solution is to copy the dataset into a clientdataset and hand over that CDS to the UI thread. Now you can bind that CDS wherever you like. Remember, that there is no connection between the CDS and the data connection. You have to take care yourself writing back the changes.
Don't know if this is relevant still. I use livebinding frequently with load time for the underlying data using treads, utilizing the TTask.Run and Thread.Queue. The important point is to have the LiveBinding AutoActivate = FALSE (i.e. TLinkGridToDataBindSource or other livebinding).
Request is done in TThread.Run with Execute of query, and LiveBinding property "Active" set to True in a TThread.Queue [inside the TThread.Run]. The Livebinding is updating UI and must occur in the main thread.
Subsequent update/request is done the same way, setting active to false first.
I'm building an app and at one point in the app I need to construct a tableView that contains 3787 items in it. (There's a search bar at the top so the user doesn't have to scroll all the way down). However it takes a good 5 seconds to insert the array into the tableview, leading to loading time when the app starts up or before going to that scene. Is there a way to trim this time down? I thought of multithreading and looked up Lua coroutines but don't completely understand the implementation to get them running asynchronously. Or how to have a loading bar while the table is loading. The table is in another scene so im using stoyboard.loadScene()
I see three options:
You load the table at app startup: this delays the startup, possibly significantly (5 seconds will be noticeable if otherwise it would be 1 second), and table may never be needed (if user doesn't go to that scene) but after that, the table is instantly ready for display
You load the table on demand (say when user clicks something): app startup fast, and table only loaded if needed, but this delays transition to scene that shows table so user may think GUI hung, so you need to let user know and provide progress indicator
You start loading table at startup in a separate thread, and most likely it will take more than 5 seconds for user to get to scene that shows table so the app startup will be fast AND it will appear to the user that table load is instantaneous when going to scene that shows table. However, there is a chance that user will try to go to that scene before the table has been completely loaded, in which case you need to provide some indication that GUI not hung but load in progress.
You just load the part of table that is visible. This may not be an option (for instance, you need to show table sorted, but database doesn't provide items with same sort so you need to load all items).
I get the impression that you can handle 1 and 2, and most likely #4 too. For 1 and 2 you need to provide some indication that a load operation is taking some time, but otherwise nothing too difficult. For 4 there is no progress needed but you need to determine which rows to load based on the "view" of table (subset of rows visible).
Option is technically more challenging. You are right that you should use coroutines. They are actually quite easy to use:
you create the coroutine at startup: thread = coroutine.create(loadTable)
loadTable should be designed to do only small chunks of work at a time, and yield in between chunks, such as
function loadTable()
...init...
coroutine.yield()
while haveMoreRows do
read 10 rows
coroutine.yield()
end
...cleanup...
end
your code resumes the thread repeatedly, until the thread dies: coroutine.resume(thread). A good place to do this would be in the enterFrame handler of corona's Runtime since this is called at every time frame.
function enterFrame(e)
if thread ~= nil then
if coroutines.status(thread) == 'dead' then
create table display so it is instantly available in table scene
if showing progress, hide it
thread = nil
else
coroutine.resume(thread)
end
end
In your scene transition (to the scene that shows the table), you should check if thread is not nil, if so then the load is not yet done so you show the message (in new scene) that table is loading; the message will get removed in the enterFrame as soon as load completed.
An important thing to know about a coroutine (cooperative thread) is that the threaded function can have multiple yield points; at the next resume, the function continues to execute from where it left off, with the correct local state.
Hopefully you have looked at http://lua-users.org/wiki/CoroutinesTutorial.
I have a method that gets called when entering a chart page in my WP7 app. It generates a List of objects and populates a ListBox. The content of each ListBoxItem is a Grid with 10 columns of data. The List gets generated incredibly quickly, even with 1000-2000 items. But as soon as the method starts building Grids and adding them to the ListBox it gets relatively much slower. Now, by this I mean it only ties up the the device for half as long as a comparable app on my 2nd gen. iPod Touch. So performance is great - as long as the user wants the data chart.
If the user hits the Start button the app exits so that's not a problem. My concern is when the user backs out to the previous page. The app just waits until the method has run. I notice similar behavior in more mainstream apps like the Kindle app. But I don't have that kind of clout with MarketPlace store! I do have a progress bar that keeps running so the behavior is the same.
Out of concern for being rejected by MarketPlace I tried putting the method into a BackgroundWorker process but that fails because it's in creating the UI elements that is where the bottleneck is and that is running on the UI thread so I get access errors. Is there a way to take a method that creates UI elements, such as a Grid, and make it cancelable?
Are you creating the UI elements within each ListBoxItem manually in code? If so, you will find increased performance by using databinding instead because the ListBox uses the VirtualizingStackPanel as the items container, so it will only actually create UI elements for enough elements to be seen and to scroll to immediately. Other elements are created when the user starts to scroll. The Silverlight for Windows Phone Performance Team have a great post on ListBox Performance.
If the dataset is particularly large you may find further peerformance improvements by using data virtualization as well (or instead) as Peter Torr explains in his Virtualizing Data in Windows Phone 7 post.
You should use the BackgroundWorker. When you need to update the UI use the following code...
Dispatcher.BeginInvoke(() =>
{
textBlock.Text = "some text";
etc
etc
}
My program do the "heavy" task (searching files and finding a signature) on a separated thread. Every task uses PostMessage to call a procedure for adding a record into a ListView.
The problem is when ListView (often) displays many records, my window will freeze. It seems my program is screaming to request Application.ProcessMessages. Only the Progressbar is still moving. After the operation has finished, everything back to normal.
If I remove the operation for adding record, the operation of my program will run smoothly.
Do you have any idea?
We once hit the limit of how many messages can be posted to the message queue. Most likely you are hitting this limit as well.
From MSDN
There is a limit of 10,000 posted
messages per message queue. This limit
should be sufficiently large. If your
application exceeds the limit, it
should be redesigned to avoid
consuming so many system resources.
From The Best Synchronization is No Synchronization
The problem with PostMessage to the main GUI thread is that you can
"saturate" the main GUI message pump,
and interfere with WM_TIMER and
WM_PAINT messages (these messages are
only dispatched if the message queue
is empty, and PostMessage means that
the queue might never be empty. In
addition, there is a nominal limit of
10,000 messages in the input queue;
after that, PostMessage will discard
the message and return FALSE. In
addition, even if the 10,000 limit is
not hit, even a few hundred messages
can mean that the user sees poor
response to keyboard and mouse input,
an unacceptable situation.
If you work with many items, it might be worth to change the overall structure of your program.
Instead of filling the list view, try filling some other data structure and then make another thread make the windows updates and use SendMessage. That way your worker threads are not stalled and you don't flood your message queue. On the other hand this would require a lot more synchronizing between the threads.
Another way would be to use some control with virtual items, such as VirtualTreeview (which can be configured to behave like a list view) That way you can fill your backing data structure and the control asks for the data as soon as an item is scrolled into view. Because even with millions of items, only a few are visible at a time, this might give you a huge boost in speed, because filling the control now is only a matter of setting the total number of items.
You should consider using a virtual grid control, like the ExGridView from roman mochalov, or Mike Lishke's very popular Virtual Tree View (Delphi Gems). When new content arrives, merely set a flag, and then decide how often you want to refresh the screen, and refresh asynchronously, but not once per new item that comes in.
One refresh per 200 mSec will be all most users can stand to see, anyways.