cancel
Showing results for 
Search instead for 
Did you mean: 

OpenUI: pure virtual function call error

Former Member
0 Kudos

Hi All,

I've implemented an OpenUI control for the Work Manager 6.1 WPF client which reads the current GPS location of the device and periodically sends it a scheduling system. The control is part of MainMenuScreen and works fine as long as the MainMenuScreen is open. It uses a Timer object to periodically run the following code to trigger an Agentry section which runs an Agentry transaction to send the GPS position:

           this.Dispatcher.Invoke((Action)(() =>

           {

               AgentryClientSDK.IAgentryControlViewModelStringDisplay vm = DataContext as AgentryClientSDK.IAgentryControlViewModelStringDisplay;

               if (vm != null)

               {

                   if (vm.DoesAgentryActionExist(SEND_GPS_LOCATION_ACTION))

                   {

                       vm.ExecuteAgentryAction(SEND_GPS_LOCATION_ACTION);

                   }

               }

           }));

If the MainMenuScreen set is closed by the user so that only the Agentry client screen with the module list, the "Go On/Offline" button etc is visible and the Timer event fires to execute the coding above, I get this error when executing vm.DoesAgentryActionExist():

As soon as the user clicks "OK", Agentry client closes. There is no exception being raised.

According to this website, the error happens if a virtual function is called in a constructor or destructor. As at that line of code my coding is not doing that, I assume that it's caused by Agentry client.

Calling the whole code could be avoided if there is a way to check whether the Screenset/Screen on which the OpenUI control is located is still open or not but I haven't found a way yet.

Also it feels for me that the OpenUI control life-cycle is a little buggy. I would expect that if you close MainMenuScreen that it gets disposed.

Has anyone faced a similar situation yet or has suggestions how to check whether MainMenuScreen is open or not?

Thanks

Accepted Solutions (1)

Accepted Solutions (1)

bill_froelich
Product and Topic Expert
Product and Topic Expert
0 Kudos

Christian,

Are you creating a thread to handle your timer execution?  Is it possible that you might spawn a thread in your control that isn't being stopped when the main form is closed?

--Bill

Former Member
0 Kudos

Hi Bill,

Yes, I'm using a Timer object which implicitly creates a thread. I was expecting that on closing of the main form the OpenUI control which holds the reference to the timer object is being disposed so that the timer would stop. But that doesn't seem to be the case. When the form is closed, my control's destructor is not called.

Do you know how I can check the form was closed or how to get notified?

Thanks

lee_bennett2
Explorer
0 Kudos

Christian,

It seems that your timer is calling after your control is not in a valid state for OpenUI calls.  At the time of the error reported above, I believe your control is unloaded, but not yet destroyed.
Try implementing an Unloaded event for your control that stops the timer, and prevents further OpenUI calls.

-Lee

Former Member
0 Kudos

Hi Lee,

thanks a lot! That's solving it.

Cheers,

Christian

Former Member
0 Kudos

Well, was happy too early. The unloaded event is also called if you switch to a different tab in the screen. (the OpenUI control is on the orders screen and the unloaded event fires if you go to notifications)

I couldn't find a form unloaded event. Do you know if anything like that exists?

Thanks

lee_bennett2
Explorer
0 Kudos

To have your behavior continue for the next screen, I think that you would need an Agentry OpenUI control added to the notifications  screen as well.  Actually seems that you would want an OpenUI control on every screen.
Each screen could create another instance of your same .NET class.  For central logic of your class, implement with threadsafe static members (e.g. lastTimeGPSSent) and methods.  In this approach, would need to track which instance is loaded in order to call the Agentry Action.

There is something else to try first.  The Agentry Main Screen (MainMenuScreen in the case of WM) might be available the entire time the application is in use.  Try adding your control to the Main Screen which might allow a single control to remain loaded while additional pages are on top.

Former Member
0 Kudos

Well, it seems that OpenUI can only be used via screen fields as only they have the "External" tab to define the OpenUI control.

The MainMenuScreen Screenset in Work Manager has multiple screens (orders, notifications, timesheet, crew management, etc). I've only found the possibility to add OpenUI controls as fields within one of those screens.

If you do that, like in my case with the GPS control on the orders screen, the control gets unloaded when you switch e.g. from the orders to the notifications screen (tab) of MainMenuScreen screenset.

Adding the control on each of the MainMenuScreen screenset's screens is probably technically feasible (will try it out) but architecture-wise not a very nice solution.

Alternatively I thought it might be possible to introduce a new screenset which has one screen which contains the MainMenuScreen screenset in a tile display and the OpenUI control in another field.

But I faced two issues with that:

1. There doesn't seem to be an official way to add a new screenset and mark it as the "main screenset" which gets loaded when you open the client.

2. I copied the MainMenuScreen screenset to ZMainMenuScreen, removed everything from the original MainMenuScreen screenset and only added the single screen with tile display and openUI control. unfortunately the TileDisplay did not display the copied ZMainMenuScreen correctly with the multiple tabs etc. Also, all rules which reference elements in MainMenuScreen break.

lee_bennett2
Explorer
0 Kudos

There is a easier way of switching to a single main screen for WM.  The MainMenuScreen for work manager (6.0) contains only a single screen for some platforms.  The iPad platform does have multiple screens.  The default configuration for the WPF client uses the iPad platform as configured in ScreenSets.ini.  So the following procedure would let you have a single main screen for testing your control:
A. In the [Win32] section of ScreenSets.ini, change the 1=iPad to another platform, e.g. Win32, that has only a single MainMenuScreen.

B. Put your control on the MainMenuScreen for the platform selected in A.

This should allow you to test this approach to verify its validity.

For a final solution I suggest moving the iPad MainMenuScreens to the MainMenu ScreenSet.  This would make the iPad platform screens more similar to the other platforms. As you state, some of the iPad navigation would also need to change.  Changes would mainly be removing special case logic for iPad navigation.

Former Member
0 Kudos

Hi Lee,

thanks a lot for all your input.

In the end, I've added the control to all tabs on the ootb MainMenuScreen and added logic to properly load and unload. It seems to be working fine.

Cheers

Answers (0)