I have a large query that needs to be loaded into memory. This query takes about 30 seconds to open. It loads immediately after the application starts, only once. During this time the application hangs. What I need to do is to update a progress bar, during the 30 seconds. I've tried to create a new thread to update the progress bar, but it will only update after the query is opened. Can anyone point a simple way to do this?
I've created a thread class:
type
TMyThread = class(TThread)
private
fLowerLimit: Integer;
fUpperLimit: Integer;
I'm creating an instance of the thread class:
CountingThread := TMyThread.Create(0, 300, True);
CountingThread.Resume;
//
SplashDlg.Show;
Inside the thread I'm just updating the progress bar:
procedure TMyThread.UpdateMainThread;
begin
SplashDlg.ProgressBar1.Position:= SplashDlg.ProgressBar1.Position+1;
MyDebug('UpdateMainThread:'+ IntToStr(SplashDlg.ProgressBar1.Position));
end;
The thread hangs while the query is opening.
It's better to paste some code here if you wish to get a more exact answer.
There are 2 ways in witch you can process data and have the UI responsive.
You can use Application.ProcessMessages in your loop.
Or the thread solution that you already approached.
The problem is I don't think you have a loop you are using a component and if that component doesn't call a method to show a progress you can't estimate how much time the query will take to complete. So either you show a loading... screen while te query executes without a progressbar or you tell us more about what you use for the query.
Hope it helps
You're doing it the other way around.
The UI is bound to the application main thread, so you always take care of the UI in the main thread, and do the real job in a worker thread (from there the worker name).
The way you're asking the question, you're already dealing with threads, so, just change your point of view and perform the heavy SQL load in a secondary thread while keeping your UI responsive and updated in the, now non-busy, main thread.
As for the 30 seconds wait time, really, if you can't determine exactly the load time is better to not use a progress bar, since we all hate that liar bars who don't reflect the real state of things. Your bar sometimes will show 50% and suddenly goes to 100%... or it may reach 100% while in fact the real thing is going to take ages to complete (heavy load on the server, slow network, and 1,000 other factors).
Nowadays, we all are used to the just wait indicators, like this:
When you see this, you know it is working, and you just have to wait until it completes.
Related
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'm working on an application that processes (possibly large reaching one or two million lines) text (in tab separated form) files containing detail of items and since the processing time can be long I want to update a progress bar so the user knows that the application didn't just hang, or better, to provide an idea of the remaining time.
I've already researched and I know how to update a simple progress bar but the examples tend to be simplistic as to call something like progressBar.setProgress(counter++, 100) using Timer, there are other examples where the logic is simple and written in the same class. I'm also new to the language having done mostly Java and some JavaScript in the past, among others.
I wrote the logic for processing the file (validation of input and creation of output files). But then, if I call the processing logic in the main class the update will be done at the end of processing (flying by so fast from 0 to 100) no matter if I update variables and try to dispatch events or things like that; the bar won't reflect the processing progress.
Would processing the input by chunks be a valid approach? And then, I'm not sure if the processing delay of one data chunk won't affect the processing of the next chunk and so on, because the timer tick is set to be 1 millisecond and the chunk processing time would be longer than that. Also, if the order of the input won't be affected or the result will get corrupted in some way. I've read multithreading is not supported in the language, so should that be a concern?
I already coded the logic described before and it seems to work:
// called by mouse click event
function processInput():void {
timer = new Timer(1);
timer.addEventListener(TimerEvent.TIMER, processChunk);
timer.start();
}
function processChunk(event:TimerEvent):void {
// code to calculate start and end index for the data chunk,
// everytime processChunk is executed these indexes are updated
var dataChunk:Array = wholeInputArray.splice(index0, index1);
processorObj.processChunk(dataChunk)
progressBar.setProgress(index0, wholeInputArray.length);
progressBar.label = index0 + " processed items";
if(no more data to process) { // if wholeInputArray.length == index1
timer.stop();
progressBar.setProgress(wholeInputArray.length, wholeInputArray.length);
progressBar.label = "Processing done";
// do post processing here: show results, etc.
}
}
The declaration for the progress bar is as follows:
<mx:ProgressBar id="progressBar" x="23" y="357" width="411" direction="right"
labelPlacement="center" mode="manual" indeterminate="false" />
I tested it with an input of 50000 lines and it seems to work generating the same result as the other approach that processes the input at once. But, would that be a valid approach or is there a better approach?
Thanks in advance.
your solution is good, i use it most of time.
But multithreading is now supported on AS3 (for desktop and web only for the moment).
Have a look at: Worker documentation and Worker exemple.
Hope that helps :)
may I ask if this Timer AS IS is the working Timer ??? because IF YES then you are in for a lot of trouble with your Application in the long run! - re loading & getting the Timer to stop, close etc. The EventListener would be incomplete and would give problems for sure!
I would like to recommend to get this right first before going further as I know from experience as in some of my own AIR Applications I need to have several hundred of them running one after another in modules as well as in some of my web Apps. not quiet so intense yet a few!
I'm sure a more smother execution will be the reward! regards aktell
Use Workers. Because splitting data into chunks and then processing it is a valid but quite cumbersome approach and with workers you can simply spawn a background worker, do all the parsing there and return a result, all without blocking GUI. Worker approach should require less time to do parsing, because there is no need to stop parser and wait for the next frame.
Workers would be an ideal solution, but quite complicated to set up. If you're not up to it right now, here's a PseudoThread solution I use in similar situations which you can probably get up and running in 5 minutes:
Pseudo Threads
It uses EnterFrame events for balancing between work and letting the UI does its thing and you can manually update the progress bar within your 'thread' code. I think it would be easily adapted for your needs since your data is easily sliced.
Without using Workers (which it seems you are not yet familiar with) AS3 will behave single threaded. Your timers will not overlap. If one of your chunks takes more than 1s to complete the next timer event will be processed when it can. It will not queue up further events if it takes more than your time period ( assuming your processing code is blocking).
The previous answers show the "correct" solution to this, but this might get you where you need to be faster.
i have an application in c# windows forms (fw4.0) and i have a method that creates a json string and send via post to an action method in a web page. I don't know how much it takes, but i want to show a progress bar while the method is executing. How can i do it?
One idea i have is to perform a counter while the method is running and show it to the user, but i don't know how.. it must be in another thread? how?
I dont have any more helpful information to provide.. i hope you can help me!
Thanks!
Use the background worker to prevent blocking the UI and to report progress.
You can report progress based on two values:
prob_time -- the most probable amount of time the action will take to complete;
max_time -- the maximum amount of time you are willing to wait before considering that the action failed;
You can make the progress bar get to a certain point(e.g. 80%) in prob_time, then to 100% in (max_time-prob_time).
If the action completes faster that max_time, you make the progress jump to 100% and report "Success", otherwise report "Failure"
Finally i did!
I have to use 2 background workers.. this is what i did..
backgroundWorker1: performs the post method.
backgroundWorker2: performs a TimeSpan counter.
when backgroundWorker2 starts, sets a TimeSpan in 0 and in the DoWork, if the backgroundWorker1 CancellationPending is false, then i report progress in backgroundWorker2.
When the post method finish, i set backgroundWorker1 to CancelAsync, so the backgroundWorker2 will terminate to.
I think that was my best solution.
I wrote a function that does alot of mathematical operations and it takes about 10 minutes to finish its work. I tried to call this function via a button on a form (Windows forms application). But the problem now is during the 10 minutes, the main form stops to respond till the function is finishing its work.
How can i solve this... any idea!
You might assign a new thread for the calculations so that the form would not have to wait for the calculation to finish to continue execution (i.e. listening to and responding to events etc.)
The problem is that, while your 10 minute function is working, the rest of the program is not executed. In particular, it cannot execute the rendering. (i.e. making your form respond).
The solution is to use threads.
As already mentioned you should assign long running tasks to a worker thread or a threadpool thread.
Keep in mind that there are limited numbers of threadpool thread. ALso Windows forms is not thread safe so you should not be directly updating the form from the created thread. You can make use of InvokeRequired.
In this case better to use BackgroundWorker class. Details in following link.
http://stuff.seans.com/2009/05/21/net-basics-do-work-in-background-thread-to-keep-gui-responsive/
Actually i am using this code and works ok, but i 'am wondering if is the correct way.
while WaitForSingleObject(MyThread.Handle, 0) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
The VCL TThread class has its own WaitFor() method that pumps the main message queue internally when called within the main thread context:
MyThread.WaitFor;
ShowMessage('i am done');
Calling Application.ProcessMessages is generally considered a code smell. Let your main thread idle if it's got nothing to do.
If you ran a company and needed one of your workers to run to the store and grab some much-needed supplies, would you then pace by the door until he got back, or would you prefer to sit in your office and rest and wait for him, and find out that the supplies are here because you hear him walk through the door? Either way, he'll take the same amount of time, but the first way's gonna wear your legs out.
Similarly, instead of having your UI watch the thread, have the thread report back to the UI. One way to do this is to have the thread use PostMessage to send a custom message to the form that launched it once it's finished, and put a message handler on the form to respond to it.
It looks correct (if correct means it do the work). What I would change is to wait for a bit more time (50ms looks good to maintain the application responsive) while not eating CPU.
while WaitForSingleObject(MyThread.Handle, 50) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
Sure there are other ways to do it... <joke>but I usually apply one of the main engineering principles:
if it works, don't touch it!</joke>
I agree with Mason Wheeler's remark, the main thread is best left to do its job, but I would suggest using the OnTerminate event on the thread. It is more 'Delphi natural' and the internal logic does the PostMessage bit for you. Since TThread is not a component, you can't view it in the object inspector and have to write and attach an event handler yourself. It gets called (in the main thread!) after the thread has completed/terminated.
While it looks okay, like jachguate I would use a bigger time-out value than 0 too. If you use WaitForSingleObject(MyThread.Handle, 100) then the main thread will wait a bit longer, thus eating up less CPU cycles.
A better solution would be the use of messages, though. Your application starts the thread and then puts all controls in disabled mode. The thread then executes and when it's finished, use SendMessage or PostMessage to the main window to notify it that the thread is done again. Then your application will just enable every control (and whatever else) again. This has as advantage that you keep the "natural" messageloop for the application alive, instead of running your own messageloop with this solution.Unfortunately, the message-method has one drawback: if the thread crashes then no message will be sent back, so a backup plan would be practical. For example, by adding a timer control to your mainform which checks every second if the thread is still alive. If not, it too would just activate the form again, disabling itself again.