You are mixing 3 different aspects: 

- how to update a UI from a background process
- how to maintain a background process over image save/open
- how to communicate between the 2

Safe UI updating has to happen using #step or #defer: and should be quick/short 
as not to block the UI. 

Although processes survive over image save/open (provided they did not become 
garbage), this is dangerous as they come up immediately (too soon) and will 
probably hold external resources (files/sockets/..) that will have changed (and 
result in a crash). It is better to manage this explicitly using #startUp and 
#shutDown.

Communication between the 2 should be protected using a semaphore.


Here is an example of a 'file watcher', a little window that shows the first 
line of a specific file, updating it every 3 seconds (silly and too resource 
intensive, it is just a demo). You can edit the file manually to modify the 
contents of the first line and see it being picked up in Pharo (within 3 
seconds).


Here is the code as 1 file/class in '_UnpackagedPackage':

Attachment: MyFileWatcher.st
Description: Binary data



See the class side #initialize for the #startUp and #shutDown registration, 
sent to all instances as #start and #stop (a bit rude but good enough for the 
demo).

Instance side #initialize sets up the mutex that gets used in the #firstLine 
and #firstLine: accessors.

The actual process is in #run which calls #updateFirstLine

The UI updating is in #step which calls #updateFileLineDisplay

Subscribing to MorphDeleted via the announcer allows for the process to stop 
when the window closes.

The file watcher window and process survive an image save/open (i.e. they keep 
on working).


HTH,

Sven


> On 3 Jun 2017, at 15:44, horrido <horrido.hobb...@gmail.com> wrote:
> 
> Okay, let me explain my application...
> 
> It displays a Morphic window containing lines of information that are
> updateable in real time on a periodic basis. As I indicated in the original
> post, the code skeleton is basically:
> 
> initA 
>   a := ((StringMorph contents: '####') color: Color white) position: (0@0). 
>   m addMorph: a 
> 
> initialize 
>   f := Form fromFileNamed: 'hot_air_balloon_mysticmorning.jpg'. 
>   m := ImageMorph new. 
>   m form: f. 
>   self initA. 
>   m openInWindowLabeled: 'Cranky'. 
>   delay := (Delay forSeconds: 5). 
>   [ [ true ] whileTrue: [ a contents: 0 asString. delay wait ] fork
> 
> Imagine that #initA creates many such StringMorphs, each displaying a
> different kind of information.
> 
> In the endless loop, imagine that instead of 'a contents: 0 asString', I'm
> updating all of the StringMorphs I created in #initA.
> 
> The need to do this in a separate thread is to prevent Pharo from being
> completely frozen during the 'delay wait', which is practically all the
> time!
> 
> Now, I did try Hilaire's suggestion to use Morphic's step protocol instead.
> But in my test scenario of closing the app/saving and exiting the
> image/restarting the image, repeatedly (in may take 10-20 times), it still
> causes the occasional segmentation fault.
> 
> So if the problem is updating a structure in the main thread from another
> process, then why did Hilaire's suggestion not solve the problem?
> 
> It seems to me, then, either way, it's an issue of multithreading...whether
> my way or Hilaire's way.
> 
> 
> 
> Sven Van Caekenberghe-2 wrote
>> Hi Horrido,
>> 
>> It is very hard to follow what you are exactly doing or trying to do.
>> 
>> Here is the simplest example I can think of that updates something in
>> Morphic on a regular basis.
>> 
>> StringMorph subclass: #MyClock
>>      instanceVariableNames: ''
>>      classVariableNames: ''
>>      package: '_UnpackagedPackage'
>> 
>> MyClock>>#initialize
>>      super initialize.
>>      self updateClock
>> 
>> MyClock>>#step
>>      self updateClock
>> 
>> MyClock>>#updateClock
>>      self contents: Time now printString
>> 
>> MyClock class>>#open
>>      "self open"
>>      
>>      ^ self new openInWindow
>> 
>> This inherits #stepTime as 1 second. If I open such a window and save my
>> image, it is still there when the image is restarted, with the clock still
>> working.
>> 
>> Updating (data structures in) the main UI process from another process is
>> dangerous. Saving such constructs is even more dangerous.
>> 
>> HTH,
>> 
>> Sven
>> 
>>> On 2 Jun 2017, at 15:54, horrido &lt;
> 
>> horrido.hobbies@
> 
>> &gt; wrote:
>>> 
>>> Sorry, I could be mistaken. I just checked my notes. The *0 asString*
>>> test
>>> failed once, but I've not been able to replicate it. I might've been
>>> working
>>> with an unclean image.
>>> 
>>> So perhaps it is related to Morphic, after all.
>>> 
>>> 
>>> horrido wrote
>>>> Yup, they all fail. Interesting that 
>>> *
>>>> 0 asString
>>> *
>>>> fails. This means it has NOTHING to do with Morphic (or Morphic being
>>>> thread-unsafe).
>>>> 
>>>> Ben Coman wrote
>>>>> On Wed, May 31, 2017 at 10:23 PM, horrido &lt;
>>> 
>>>>> horrido.hobbies@
>>> 
>>>>> &gt; wrote:
>>>>> 
>>>>> Can you try a few other variations...
>>>>>  [ [ true ] whileTrue: [ 0 asString. delay wait ] fork.
>>>>>  [ [ true ] whileTrue: [ a contents: '0'. delay wait ] fork.
>>>>>  [ [ true ] whileTrue: [ a contents: '0'. ] forkAt: 20.
>>>>> 
>>>>> cheers -ben
>>> 
>>> 
>>> 
>>> 
>>> 
>>> --
>>> View this message in context:
>>> http://forum.world.st/Morphic-or-forking-bug-tp4948727p4948984.html
>>> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
> 
> 
> 
> 
> 
> --
> View this message in context: 
> http://forum.world.st/Morphic-or-forking-bug-tp4948727p4949166.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.

Reply via email to