I want to start a process when some user-initiated action occurs. If the
user repeats their action before the process has completed, I want to stop the current process and start a new one. I have the following code in a subclass of Shell, where process is an instance variable. onSomeEvent process notNil ifTrue: [process terminate]. process := [self doSomething: self someMessage] forkAt: Processor userBackgroundPriority] It looks like if the current process has completed, then all is well, but if the current process has not completed, then the first line of the method is executed, but not the second. I tried putting in 'process := nil' after 'process terminate' which had no effect, and I also tried changing 'userBackgroundPriority' to higher priorities, again with no effect. Any help would be appreciated. -- Louis |
Louis Sumberg wrote:
> I want to start a process when some user-initiated action occurs. If > the user repeats their action before the process has completed, I > want to stop the current process and start a new one. I have the > following code in a subclass of Shell, where process is an instance > variable. > > onSomeEvent > process notNil ifTrue: [process terminate]. > process := [self doSomething: self someMessage] > forkAt: Processor userBackgroundPriority] > > It looks like if the current process has completed, then all is well, > but if the current process has not completed, then the first line of > the method is executed, but not the second. Hi Louis, From the description of the problem, it sounds like the #onSomeEvent message is being sent in the "process" Process. You could confirm that with an assertion: onSomeEvent process notNil ifTrue: [ self assert: [Processor activeProcess ~~ process] ....] .... If so, you could probably fix the problem by sending #onSomeEvent in the "main" process using: SessionManager inputState queueDeferredAction: [self onSomeEvent]. I have methods that look like yours, and I have had no problems with them, however I do try to cleanly separate methods and state that control the forked process, from the messages that the forked process sends. At the least it makes the code easier to test. > I tried putting in > 'process := nil' after 'process terminate' which had no effect, In this case, since you are creating a new process immediately I dont think it is necessary, however terminating a process that is not the active process does lead to an interesting chain of events. While you can send #terminate to a process twice, I avoid it, and in D5 I have been using something like: process ifNotNil: [ :theProcess | process := nil. theProcess terminate]. A couple of other thoughts, while not relevant to the code fragment you posted, they may be to the bigger picture: - Are you assuming any timing order between the first process being terminated (and any unwind blocks being evaluated) and the second process being started? - Are you doing any clean-up before terminating the process. For example: process notNil ifTrue: [ self doCleanUp. process terminate]. To get the #doCleanUp send out of the controlling process, this could be rewritten as: process := [[self doSomething: self someMessage]] ensure: [self doCleanUp]]. forkAt: Processor userBackgroundPriority] Steve -- Steve Waring Email: [hidden email] Journal: http://www.stevewaring.net/blog/home/index.html |
Hi Steve,
Wow. Thanks for the wealth of information. > From the description of the problem, it sounds like the #onSomeEvent message > is being sent in the "process" Process. You could confirm that with an > assertion: Yes, that confirmed it alright. However, see below, I really don't understand. > If so, you could probably fix the problem by sending #onSomeEvent in the > "main" process using: > > SessionManager inputState queueDeferredAction: [self onSomeEvent]. I'm still not understanding something. Like ShellExplorer, #createSchematicWiring sets up an observer (on a ShellTreePresenter) that calls #onFolderSelectionChanged when the user clicks on a folder. Unlike ShellExplorer, I want to spawn a process in #onFolderSelectionChanged (which we probably would have had to do in ShellExplorer if it wasn't so fast) that can be killed when the user switches to another folder. Isn't #onFolderSelectionChanged, as with all UI events, coming in on the "main" process, i.e., the Dolphin thread? I tried putting your suggestion above in a couple of places, but I got the same assertion failure. > I have methods that look like yours, Sorry to hear that :) > ... I do try to cleanly separate methods and state that control the > forked process, from the messages that the forked process sends. I suspect understanding the above will help me understand this part too. Thanks also for the heads-up on timing and clean-up. No doubt I'll be getting to those. -- Louis. |
Hi Louis,
Louis Sumberg wrote: > switches to another folder. Isn't #onFolderSelectionChanged, as with > all UI events, coming in on the "main" process, i.e., the Dolphin > thread? Not necessarily. If your forked process manipulates the model, then events can be triggered and handled in the forked process. Looking at TreeView and the selectionChanged event, it might be as a result of nodes being deleted or collapsed by the forked process. Does that make any sense? I think good practice is to keep what the forked process does (and accesses) separate from your UI models, and always send messages to a model (ie a ListModel or TreeModel) in the main process. Even still, I wouldnt start forking processes without carefully considering the added complexity. As an example your doSomething: method could look like: [| newNode | newNode := self getNextSlowThing. SessionManager inputState queueDeferredAction: [treeModel add: newNode asChildOf: newNode parent]. self hasMoreNodes] whileTrue If that doesnt help, can you send me the changes to ShellExplorer which show the problem? Thanks, Steve -- Steve Waring Email: [hidden email] Journal: http://www.stevewaring.net/blog/home/index.html |
In reply to this post by Louis Sumberg-2
On Mon, 20 Jan 2003 14:20:38 -0800, "Louis Sumberg"
<[hidden email]> wrote (with possible editing): >I want to start a process when some user-initiated action occurs. If the >user repeats their action before the process has completed, I want to stop >the current process and start a new one. I have the following code in a >subclass of Shell, where process is an instance variable. > >onSomeEvent > process notNil ifTrue: [process terminate]. > process := [self doSomething: self someMessage] > forkAt: Processor userBackgroundPriority] > >It looks like if the current process has completed, then all is well, but if >the current process has not completed, then the first line of the method is >executed, but not the second. I tried putting in 'process := nil' after >'process terminate' which had no effect, and I also tried changing >'userBackgroundPriority' to higher priorities, again with no effect. > >Any help would be appreciated. > >-- Louis > Just a thought - couldn't you use a singleton to keep track? -- Larry [hidden email] |
In reply to this post by Steve Alan Waring
Hi Steve,
> If your forked process manipulates the model, then events > can be triggered and handled in the forked process. <snip> >Does that make any sense? Yes, it makes sense, or at least enough sense that I know not to go there for now. *s* I've managed to get it to work by removing the process instance variable and still forking a process, and essentially putting the code that's forked in an Error block. This has the effect that when a new process is created, state in the old one is invalid and so an Error bubbles up, is caught, and the old process dies a quiet death. Also, the app I'm working on is not ShellExplorer, sorry for the confusion. It's actually the NickelViewer (for viewing thumbnails) I mentioned the other day. So far, the app itself doesn't have a model *gasp*, but it uses a ShellTreePresenter (which does, of course, have a model, and is where onSelectionChanged is caught). Thanks again for your time, effort, and help. -- Louis |
In reply to this post by L. M. Rappaport
> Just a thought - couldn't you use a singleton to keep track?
Larry, thanks for the suggestion. I don't understand how that would work though. In the meantime, I think I've solved this particular problem. -- Louis |
Free forum by Nabble | Edit this page |