276 views
in GUI Development by

Hello,

I have created a test page which is linked to some hardware signals to test a device functionality.

In this page I have created some property like ManualEnable, ManualSpeed, ecc that I use to control signals in this page (set/reset some hardware output, PWM, DAC and so on).

The OnSet method for each propery set a "native" output variable (global variable in the device integration code) which is linked to the hardware in a thread running in background.

So, to set an output, the corresponding variable must be set (for example, to set enable output, the boolean variable of a struct "Out.enable" must be set to true).

When I switch to another pages from this page, I need to reset all the outputs, stop PWM and set DAC to 0 value. How and where can I do this?

I tried to do this in te Done method, but got the following error:

The method OnSetManualFeederEnableBoth is this:

// The value doesn't change - nothing to do.
if ( pure ManualFeederEnableBoth == value )
  return;

// Remember the property's new value.
pure ManualFeederEnableBoth = value;

$if !$prototyper
native (value)
{
  if (value)
  {
    Out.df_not_reset = 1;
    Out.df_not_enable = 0;
  }
  else
  {
    Out.df_not_reset = 1;
    Out.df_not_enable = 1;
  }
}
$endif

I thought to do it in the Done() method just before the page is "deleted".

But I don't understand why I got this error.

PS: to change page I use the SwitchToDialog command.

Nicola

 

1 Answer

0 votes
by

Hello Nicola,

Done() methods are limited in their possibilities. They can access data members of this object only without accessing other objects referenced eventually from this object. This is because Done() method is invoked for objects designated for destruction shortly before they are freed. The order in which the objects are destroyed is not predictable. This may produce errors where object A is referring object B and object B is already freed. Trying to access object B from Done() method of object A would cause runtime problems.

So far the technical background for the error message.

In your case I don't see any access to foreign objects from the property. Also trying to reproduce it with your code above didn't report the error. Therefore I suppose there is some more functionality in the method OnSetManualFeederEnableBoth and/or Done() method. I would recommend to review both methods. Take in account the above described limitation for Done() methods.

Which EW version are you using? Versions older than 10.0 were more restrictive concerning the Done() methods.

Best regards

Paul Banach

by

Hello Paul,

thank you for the technical background.

Actually, in the Done() method I also have this code:

notifyobservers ^OutputFeederNotEnable;

notifyobservers ^OutputFeederNotReset;

which purpose was to update the view to some outputs (but it didn't work because I didn't also change the properties OutputFeederNotEnable and OutputFeederNotReset).
So to "reset" the outputs and stop the PWMs when a page changes, the solution is to create a slot method and call it in all the functions that change pages (along with SwitchToDialog). Or are there other solutions that you suggest?

by

Hello Nicola,

while Done() is executed, the object is already considered as garbage. Eventual relations with other objects don't exist anymore and other objects can't receive notifications from the object. Your approach will therefore not work.

My recommendation would be to copy the native code directly into the Done() method without performing any other operation in the Done() method. For example:

$if !$prototyper
native
{
  Out.df_not_reset = 1;
  Out.df_not_enable = 1;
}
$endif

When I switch to another pages from this page, I need to reset all the outputs, stop PWM and set DAC to 0 value. How and where can I do this?

Please consider, the garbage collection may work with delay. That means the Done() method may be invoked after you switched to a new dialog. If the new dialog performed some PWM setup, the Done() method in the old dialog will deactivate it again due to the delay.

My recommendation would be to put the communication with the device inside a Device Class. The UI components should then be free from the native code. Instead, the UI components should invoke methods of the Device Class or access properties existing in the class. The Device Class could also implement a kind of state machine to track the initialization status of PWM, etc. On the other hand, at the time when you perform SwitchToDialog() you can invoke a method in the Device Class to perform the desired status updates.

I hope it helps you further.

Best regards

Paul Banach

by
Hello Paul,

Ok, I have understood the situation better.

I will follow your suggestion and implement a machine state in the Device Class.

Thank you for the help!

Best regards.

Nicola

Ask Embedded Wizard

Welcome to the question and answer site for Embedded Wizard users and UI developers.

Ask your question and receive answers from the Embedded Wizard support team or from other members of the community!

Embedded Wizard Website | Privacy Policy | Imprint

...