Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to interrupt a running VFP app without having VFP interrogating an outside file, device or other 4

Status
Not open for further replies.

dkean4

Programmer
Feb 15, 2015
282
US
I know how to use a timer to trigger an occasional interrupt like... "Is there a file named 'xxx.txt' in some subdirectory". But now I need some "shell" or another way to flag a running VFP app so that the user can use his/her app without interruption. Can 2 independent apps be running concurrently while one passes occasional flags? I do not want the user to be aware, "Yoh, dude, I need to tend to something else for a moment. I'm stopping you for the next 15 seconds"

Any help would be very appreciated.

Dennis Kean


Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
So, you are asking if it is possible to have two concurrent apps, and for them to communicate between themselves? If that's right, the answer is Yes.

The simplest way is for one of the apps to create a small file - such as a text file - that the other app will periodically look for and read. The file can contain whatever information you like. I've used this method, and it has worked reliably.

It is also possible to use a DBF in this way. I've done that as well, but the method has some glitches which are not obvious. If you want to follow that up, let me know and I will look at my notes so that I can tell you more.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I was wondering how you do that without some kind of semaphore, file or table?

There is no process to process communications provision - wouldn't that require multi threading?

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

There is no place like G28 X0 Y0 Z0
 
Dennis,

VFP still has DDE !

so one (background?) process would ddesetservice() and ddesettopic()

and the other (UI) process would ddeinitiate() and ddeexceute() or dderequest()



hth

n



 
Would there be much benefit over using a file/table semaphore though?

You would still need to periodically see if a dde request had been initiated
and then act upon it, it couldn't 'interrupt' a current action could it?

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

There is no place like G28 X0 Y0 Z0
 
Griff,
perhaps no benefit. But a dderequst() from one (UI) process does cause an "event" in the receiving process (in that the ddesetopic passes a UDF to fire when the topic is called by the first (UI) process.)

i mention it a bit tongue-in-cheek... it's more or less deprecated but it does still work.

if it were me i'd probably create my own message queue... one process puts a request record into a table somewhere and the other (on a timer) picks up unprocessed records, does the necessary and posts a reply. Has the advantage that the two don't even need to be on the same PC... and messages queue if the 'server' process is down or busy (and gives diagnostics/history)

n
 
It would be handy if Dennis would let us know if our interpretation of his requirements are correct.

But in the meantime, I mentioned earlier that I had once used a DBF in this way (as a semaphore). I've just found the program where I did that (written 11 years ago). I don't know if this is relevant to Dennis's question, but I'll describe it here in case anyone is interested in doing something similar.

In short, I had two programs: a foreground process (with a user interface) and a background process (no user interface). The foreground launches the background, then sets it to perform a task. There is two-way communication between the two;

- The foreground sends a message to the background to tell it to start the task or to tell that the user wishes to cancel;

- The background reports its progress to the foreground, which then updates a progress display in the UI.

Both programs exist as EXE files. The foreground creates a temporary table (the semaphore). It then uses ShellExecute() to launch the background, passing the path and name of the semaphore file as a parameter.

When the user signals that they want to the launch the background program's process, the foreground writes a "message" in the table (the message is just a mumeric value). Every so-many milliseconds (2,000 by default, but the programmer can change this), the background checks the semaphore. (This is done with a timer.) If the message is present, it starts the process.

There is a similar action if the user decides to cancel.

Periodically during the background process, the background program writes a message to the semaphore to indicate its progress (typically, a percentage complete figure). It does this in the process's main loop.

The foreground then checks the semaphore every so-many milliseconds (again, with a timer), and reports the progress to the user.

Basically, that's all there is to it. When I developed this, I was amazed at how slick it was. I thought that the background process (which by its nature is processor-intensive) would slow down the whole system, but in fact the user was able to continue to work in the foreground without any apparent drop in performance.

I don't claim that this approach is in any way original, of course. But it served its purpose, and as far as I know is still in use.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Interprocess communication (IPC) is the key word here.

GriffMG said:
There is no process to process communications provision

If you mean native functions and commands of VFP supporting IPC, then you're half ways right, but besides files used to communicate you can make use of BINDEVENT, of course. And send messages on the other end. Also, do it both ways around.
It also depends on whether you need to do this peer-to-peer on two different clients, so the IPC needs to make use of the network, or whether it's IPC between two processes like the already proposed idea of a foreground (Interactive with the GUI) and background (non-interactive, without GUI) process for doing things in parallel.

The mechanisms acting on the same computer are well known if you ever configured MSSQL communication protocols: Shared Memory is local, and pipes can be local or go through the network, even TCP/IP can go to localhost aka the same machine. For peer-to-peer communication (in detail ports/Winsock) you usually need to allow requests to go on routes usually only allowed for responses, so network admins won't like such solutions. The simplest way to communicate over the network still is via files on a share.

The other ingredient is that you want to not poll for signals but want a signal/flag to cause an event. And in that case, BINDEVENT is the simplest solution. You cannot only bind to the VFP class events, you can bind to Windows messages, and that does not only include all the messages coming from the OS but also user-defined messages.

If you look for IPC sessions at many VFP conferences all over the world you surely find some material to make use of.

I still wonder what is causing blocking when you make use of a timer. On one side I understand it's a bit cumbersome to need to poll for something to happen, like a file becoming existent, but let's say your timer runs 10 times a second, a FILE() or ADIR() check only takes split seconds and doesn't bog down your CPU and doesn't make your user interface unresponsive.

Especially since that waiting for a signal through a timer will happen in the background EXE, not the EXE that has the user interface, that should be the process that causes the other to act, not act itself, so it'll not be blocking the UI, it'll only write the file or add a record to a DBF to trigger the other process to do whatever in a non-blocking way.

Well, and a second EXE means another process. Whatever another process does is not blocking, unless you actually bog down CPU/RAM/network with whatever you do so other processes are influenced. Usually not, even way back when we only had single core CPUs Windows already managed to run tens if not hundreds of processes in parallel by giving each process time slices on the CPU, that's automatic and still automatic in the era of multi-core CPUs, there's nothing to do. So that should answer the main question you had:

dkean4 said:
Can 2 independent apps be running concurrently while one passes occasional flags?
Yes.

Unless you mean APP as in VFP APP file that you run by DO. That's not starting a new process, that runs within the same process, not in parallel. Even DOing an EXE doesn't start a new process, by the way, so the problem is DO, not the file extension.

And all that said, now it will depend on the nature of the communication you want to establish between the two processes, whether you actually need IPC or not. Not only the timer polling for a file is one solution to that if you only want to start something that runs in parallel as long as it needs without blocking your user interface then all you need to do is RUN another EXE using the /N option so it does not wait for the new process to finish. Well, take a look into the help of RUN for the /N flag. Other options are CreateProcess Windows API, besides others in the same family of process-starting API functions. ShellExecute is another possibility.

There are naturally some gotchas. A new process is a new process, it needs all info passed in via parameters or externally, for example by files. But then you have a database system, you can "pass" on a whole database. Just don't program the background EXE to know any of the properties/states of the main interface EXE, of course, not even the default path. It's a new process and you need to provide anything that the new process needs to know to do the background task, ideally completely independent from whatever the main process continues to do.

Coming back to the point where I said Griff is halfway right. On one side Nigel already talked about DDE, which is part of the VFP language on both ends of sender and receiver, while BINDEVENTS only is on the receiving side. But you only need the SendMessage API function declaration to be able to send out those messages another process waits for via its BINDEVENT. It doesn't involve actively waiting and polling for signals, once you make the BINDEVENT binding you wait for any instance of a specific message number, without a timer becoming active every interval. If you send a message the response on the other side is immediate and can do whatever in the other process without interfering with the responsiveness of the UI of the main EXE process, which sent that message, i.e. sending a message is not waiting for a response.

If you bog down the network or CPU, RAM or I/O, that's another story, but if whatever you'll do in parallel is that resource hungry you better implement it on some server and not just as a background process.

If another process doesn't suffice, you can run as many parallel processes as you like, the natural limit is the number of physical or virtual cores that actually can run in parallel and if any resource is needed exclusively multiple processes also can't accelerate things, obviously, but it would actually be hard to bog down the process that keeps being the UI for the user. It's really parallel running code.

And signaling to finish or returning a result? That return path has multiple options, too, you can again use the Windows message system or any of the IPC mechanisms.

One thing is sure, just like with DDE or files, you of course have to know things in advance. The DDE topic that is used, the port number, the windows message number, the name of a named pipe the file name, there is no IPC only programmed on one side that needs no control over the code of the other side, the minimal requirement is that the other process already uses some of the IPC mechanisms, i.e. it already generally listens for input on a StdIn pipe. You can't inject, establish the receiving end and force another process to listen on this channel, so it's always a two-sided implementation, even with the simplest of shoot-and-forget with RUN /N the called EXE has to expect the input parameters/files it needs to do whatever it should do. So, even one-way communication needs a "contract" to agree on. The only way the other EXE doesn't need to know anything in advance is when you'd write the code and BUILD and then RUN it, but that's surely a recipe to trigger an antivirus system. A milder variant would be EXECSCRIPT, but that does run in the same process again.

Chriss
 
Dennis,

You posted your question ten days ago, since when you have received several suggested solutions. It would be helpful to have your feedback on these. Which, if any, of the suggestions were helpful to you? Do you still have the problem?

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
myself said:
Just don't program the background EXE to know any of the properties/states of the main interface EXE, of course, not even the default path. It's a new process and you need to provide anything that the new process needs to know

Having reread that, I want to add, this only is true as far as you only create/run/start/execute a new process in the shoot and forget manner.

As initially said
myself said:
it will depend on the nature of the communication you want to establish between the two processes, whether you actually need IPC or not
Which has the other aspect, that with IPC you can establish two-way communication.

But I still don't know if any of that helps you, as you said "interrupt", not communicate with. There is no "suspend" you could send to another VFP process, so it has to react to IPC inputs to suspend itself. The only tool you have is sending ESC to a VFP process, which doesn't suppress the ESC functionality to interrupt the VFP process and offer the program error message box "*** INTERRUPTED ***" with suspend as an option. I think, though, even if you don't SET ESCAPE OFF, the suspend option is only available within the IDE, but the process is in the interrupted state with ESC and the cancel button will end it, the ignore will let it continue.

That's not a mechanism to intentionally use just for pausing a VFP EXE. And the details you posted about keeping an application responsive and usable to the users suggests, you want something else, which is why I skipped that part.

There surely is more to say, as there always is, but I second Mike Lewis, it's time you continue your thread with a response to the suggested solutions.

Chriss
 
Mike,
Sorry for the delay and thank you all for the input "Mike Lewis, Nigel Gomm, GriffMG, Chris Miller... ". I had some business to attend to which left me little time to do anything other than...

I am now reading all your posts and am very grateful for all the ideas. At this moment I am processing it all. I think that most if not all understood the issue. Please give me one more day to make some comments. I need to grasp your replies accurately... Later today. I will respond rationally,

Once again, many thanks to each one of you... I will respond shortly...







Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
Nigel Gomm

If you have some code for DDE to offer, which works, I would love to see it. I looked into that years ago and did not construct it properly. The problem might be if the call to the main process creates an interrupt. The main process is reading text to speech and interrupting would cause hesitations which would become annoying as the data exchange is taking place between the two independent processes. One solution might be for me to break up the speech processing into separate sentences. (Send one sentence at a time to the speech module.) I have been working on that today. But it is not ideal.

If you have some code, I would like to see it and it might be useful for another project I am working on as well.

Thank you for your suggestion. Very interesting...



Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
Mike Lewis
To your first comment, "The simplest way is for one of the apps to create a small file - such as a text file - that the other app will periodically look for and read." That is a good idea. I often use that. Ultimately, two independent VFP programs are the way to do that. I hate to have two separate applications to maintain separately. It requires more effort to install them on clients' desktops.

So, you understood the problem correctly. I was wondering if there was some tricky way to do multiprocessing. I think that loading sentences separately is a way to allow moments of using semaphored bouncing. So, your reply was adroit and thank you for that, Mike.

Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
GriffMG

Yes, Griff, multithreading is what I was hoping might work. I thought that there was something about multithreading in VFP. I read something making me think that in 2009. The problem I presently have is that "Text-to-Speech" overwhelms the running module. It dislodges the subtle screen refresh of the application, which is a severe annoyance for me. So, the next thing I have been indulging in is fragmenting the speech into sentences. But that too has some repercussions when the page refreshes. Text-to-speech overloads the app like nothing else. The page turns into a semitransparent image until the text spoken ends. I might have to use something other than MS text-to-speech. If you have any ideas, let me know.

Thank you for thinking along... I always appreciate your comments...

Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
Chris Miller

Sorry I tested your patience. I had a busy week until this afternoon. Thank you for your eloquent reply. I enjoyed your post a lot. You really dug into this. Concerning the core of the issue, it is Text-To-Speech. If you have ever used it, you know that it takes over and catapults the VFP EXE into oblivion. But when it returns from a long paragraph, all is hunkey Dorey, except for many items on the screen which are left discombobulated. VFP becomes unaware of the Mouse cursor, its click buttons, and just about everything, including the Keyboard.

Due to that problem, I am now trying to spend as little time as possible in the TTS. That means I am sending sentences, not whole paragraphs. VFP goes numb when TTS is active. MS never mastered TTS. Interrupting TTS is a big No-No! And yes, I was hoping to be able to rip VFP out and stop TTS if not pause it for just a moment between words. So, Multithreading would be glorious if viable with VFP, but if TTS is unreachable, then Sayonara! IPC, I realize now, will not work either. Under the TTS call, VFP goes on a vacation and returns when done. So, sentence fragmenting is my only way to slice into the TTS consciousness. That is the hijacking you wanted to figure out, Chris.

You sure made me think, Chris, and I thank you for that.



Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
Mike

Concerning your post:
"In short, I had two programs: a foreground process (with a user interface) and a background process (no user interface). The foreground launches the background, then sets it to perform a task. There is two-way communication between the two;"

Clearly an excellent Idea. I use it all the time. Thank you for making it so easy to grasp, as always. But the issue is the TTS I use. It is MS's looney concoction. It isolates the main program and does not let it respond to anything.

Thank you for an excellent explanation, Mike.

Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
First thought about TTS, as it is so making the process that executes it unresponsive of interactions/mouse moves/clicks, wouldn't that suggest to do TTS itself in a background process?

Multiprocessing is much easier than multithreading. There is a solution allowing multithreading from Calvin Hsia, but that means creating code from data and as that's a process viruses use it's usually not allowed by "data execution protection" (DEP). you can turn that off and use Calvin Hsias approach.
But it's complicated. Not easy to do this on a setup and likely not tolerated by administrators of some companies as it undermines security.

Well, while there are other ways, too, multiprocessing is easiest, isn't it? So why not simply create a TTS EXE, say vfptts.exe which you give a text to speak as a file by command line parameter and then run it with

RUN /N vfptts.exe "&FullFilename" && including path

vfptts.exe

It's no problem at all to have two EXE in one setup, the second EXE is just a file as any other, databases, image files, whatever. And the VFP runtimes are installed anyway for your main VFP process. You remove the TTS from it and have no interface blocking.

What problem do you have with this? Isn't it the straight-forward solution? Remove the problematic TTS from the main process and do it in a separate EXE.



Chriss
 
Aside of this simple solution I doubt you're right that a process doing TTS can't react to windows messages. There are system windows messages processes receive at any time and if they can't react that would cause problems, so even if TTS spikes a core to 100% I don't think it stops message processing by BINDEVENT.

This remark in the help of BINDEVENT points out how windows messages are working even in modal states of your application:
help said:
With a Windows message event binding, your user code will execute whenever an event occurs including scenarios in which a modal dialog is displayed. This is because the Window Procedure must always process the message and return. Since it is possible for recursion to occur with an event while your user code is executing, you may want to specify an nFlags value of 4 to prevent this from happening.

You might think of the message queue of windows only being processed if VFP is in its READ EVENTS state as that means "event processing". It's worth checking.

On the other hand a RUN /N vfptts.exe would not need any further messages sent to it, would it?

Chriss
 
Chris Miller

I have never seen this version of TTS -RUN /N vfptts.exe-

I set up the SAPI version supplied by MS as follows:

Code:
FUNCTION Setup_Voice()

PUBLIC Speaker, Speaks
	Speaker = CREATEOBJECT("SAPI.SpVoice")
	Speaker.Rate = 1.7
	speak("Voice enabled!")
RETURN 
ENDFUNC

FUNCTION speak(wordes,delay,person)
	DO CASE 
	CASE VARTYPE(person)="C"
		DO CASE 
		CASE UPPER(person) = "RYAN"
			person = 0
		CASE UPPER(person) = "PAUL"
			person = 1
		CASE UPPER(person) = "ANNA"
			person = 2
		CASE UPPER(person) = "HEATHER"
			person = 3
		OTHERWISE 
			person = 1
		ENDCASE 
	CASE VARTYPE(person)="N" AND person >-1 AND person<4
		* 
	OTHERWISE 
		person = 2
	ENDCASE 
	
	speaker.voice = speaker.getvoices().item(person)
	
	speaker.Rate = 0.3
	IF EMPTY(delay)
		speaker.speak(wordes)
		*speaks.trigger(wordes,0,person)
	ELSE 
		speaks.trigger(wordes,delay,person)   
	ENDIF 
	
RETURN 
ENDFUNC

I assume you thought that I was using an external app. Microsoft supplies this object. I have used it forever. If you know an external TTS.EXE with various voices please let me know!




Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
Chris Miller

I only read your second message... did not see the first one. Yes, I thought of doing that. Create a separate VFP application to process TTS externally. I am so used to Microsoft's TTS Object that I take it for granted to be used integrated into the running app. Thank you for suggesting that. I will get off my bum and do it that way. I appreciate your suggestion. That sounds like a solution.

Dennis Kean

Simplicity is the extreme degree of sophistication.
Leonardo da Vinci
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top