Interrupt a process

First off… a Thread doesn’t work here, there is too much interaction with the GUI required… I tried and it would require me to totally re-engineer quite a few custom controls :frowning:

So here is the situation.
I have a custom control that takes a text file (which could be VERY large), and parses it in to columns of valid data.
as each column is extracted, it calls an event which notifies the window that there is a SINGLE row to be dealt with
If a method on the window decides that returned data is invalid, it signals the custom control to stop processing.

What I need to do is have a BUTTON on that window that can also abort the process… but so far that button doesn’t seem to fire until the custom control is completed, or programmitcally aborted.

I CAN do it by using the “EVIL” app.doEvents…
but wouldn’t that also get an AppleStore reject?

App.DoEvents will not get you rejected from the MAS.
But really, you need to reengineer to do threading properly.

Like I said there is way way too much interaction with the GUI, and using “timers” to intervene would slow things down too much, as this process really needs to run as fast as possible… I’m not worried about the user being able to abort a short process, but it is when there are millions of records, and they decide they don’t want to wait .

As of now… the App.Doevents… added maybe 0.001 seconds to my test, but gives me the ability to abort at will.

By not using a thread your UI CAN’T be responsive the way you want - thats the actual point of using a thread but …

Using a hack like DoEvents opens you up to weird behaviour because it can cause the main loop of the app process to run recursively

A thread is the right way to do what you want but you’re not amenable to that so …

Sorry, you need to use a thread.

Properly coded, a thread will use almost 100% of the CPU (and thus be just as fast as non-threaded code) but still allow the foreground UI to be responsive.

It’s a pain the first time you do this, as it seems like a lot of trouble, but once you’ve done this sort of design pattern once you will see it’s really the way to go.

Norman, I NEVER said that… What I DID say, it that the amount of required UI interaction during the process that “should” be given to a thread is extensive… it has to update logs (textarea, progressbars, and sometimes even ask the users decision before proceeding).

So even if I were to put it in a thread, I doubt there would be any “real” benefit as the extra band-aids to keep the UI up to date would add to the amount of time required to complete the task. And in this situation, the GUI is locked as far as the user interacting with it down on purpose with the exception of a single “ABORT” button. There is nothing they can or should be doing until it completes, sometimes this is a few seconds, but if they hand it a 10gig file, it will take a while.

FYI… my biggest issue with a thread right now?
The window has my custom control on it (a non-visual control)… but the thread (also on the same window) says it doesn’t exist, yet

My control has a method called “PROCESS”
if I call “PROCESS” from then “OK” button, it does what I expect
If I replace the call with “THREAD1.RUN” and place the PROCESS call in the RUN event, then all of a sudden the custom control isn’t available anymore.

“PROCESS” deconstructs a file and raises an event when it has a “packet” or record to be processed… similar to I’d guess an HTTP socket except the data is from a local file… And SPEED is required

I’ve used this technique with great effect.

Create a Timer and properties to hold an index and the data you want processed. When you need to process, start the Timer with a minimal period, like 1. At the start of the Timer.Action, record the Ticks then resume with the next index. Keep looping until the elapsed time is >= 3 ticks. Record the next index and exit. When the loop is finished, stop the Timer. This sort of emulates what a Thread does but keeps your UI accessible and responsive.

Why not return true from the event to stop the process? Then the abort wouldn’t be immediate but on every line you would have the opportunity to check a boolean, to see if the abort button was pressed.

Never the less… In my experience on windows, methods running longer than 5 or 6 seconds result in “The App (Not Responding)”. The only alternatives I know of are a timer or a thread.

Ok… not sure why I’m having an issue with this… :frowning:

I have reengineered the entire “custom control” into a single “method” which is basically a For/Next loop with a bunch of processing inside. During that process if messages are generated they are placed in a queue
A timer on the calling window executes this action ever 1/2 second or so

		getMessage // get any messages from the queue and move to the TextArea in the GUI
		If Thread1.state=Thread.NotRunning Then 
				btnCANCEL.caption="Done"
				Me.Mode=timer.ModeOff
		End If

What I’m confused about… is what do I need to do to yield to the GUI???

What do you mean? The thread should yield to the GUI based on the priority you set.
http://documentation.xojo.com/index.php/Thread.Priority
You can also use YieldToNextThread in a tight loop within the thread if you really need to.

Also, because I know you don’t want the process to feel long, I usually use a period of 150 on a timer that’s sole purpose is to pass messages out of a thread, the UI stays active and everything feels smooth.

Well darn… you are right… not sure WHY, but it did do what I wanted

Another technique I’ve used is to make thread-safe control subclasses. Imagine a TextArea or Pushbutton subclass which has the normal methods which (when called from a thread) simply set up an internal timer callback to do the right thing. With these in place, you can write your threaded code without worrying about UI issues. It’s very clean and makes a lot of sense once it’s working.
(I really should put these classes up on GitHub or something).