Jump to content

Asyncronous invokation of ActiveX instances


_Y_

Recommended Posts

Hello all,

I encountered quite a puzzling problem. May be some of you know a solution or some trick.

Shortly

As a rule, Invoke Node works asynchronously. If two Invoke Nodes are called in different loops, threads, or processes, they are executed independently. But it does not happen if they are used to execute some function of an ActiveX (OCX file).

I need to invoke the same function of an ActiveX asynchronously. Of course, I create two instances of the ActiveX but, the Invoke Node that is called first blocks execution of the second; i.e. two invocations are executed consequently.

I need a “pure-asynchronous” execution but could not find any solution.

Some interesting experiments

Experiment 1. I created an ActiveX containing only one function. The function simply waits for a number of milliseconds than returns a String value. If called from a non-LabVIEW program, two instances of the ActiveX work asynchronously without any problem. But it is not so in LabVIEW :(

Experiment 2. To do a “pure” experiment, I created two independent ActiveX-es. Both have the same function but even names are different. This block diagram shows the same test but with two different ActiveX-es (the same code as in Experiment 1 but the ActiveX holders point to two different ActiveX-es):

nTJs07vP.gif

Two Invoke Nodes are not executed asynchronously. They wait for each other.

Experiment 3. This experiment is probably most puzzling. I created a sub-VI that do exactly the same – waits for a number of seconds. Of course, if such a sub-VI is reentrant, its instances can be invoked asynchronously. Now I tested what happens at parallel use of Invoke Node on instance of the ActiveX and on the sub-VI:

3ni1ukoR.gif

Now - the show! If the sub-VI is invoked first (bottom structure), the ActiveX is invoked asynchronously. But! If the ActiveX is invoked first, invocation of the sub-VI waits! :blink:

Thanks in advance for all ideas.

Link to post

Phillip Brooks, thank you for the link. Unfortunately, that discussion solves invocation of an ActiveX incorporated in a DLL. At least, I understand it in such a way.

To my knowledge, DLL-s are called using Call Library Function Node that is configurable and can be set for execution in a non-UI thread.

I call the ActiveX directly; i.e. using its reference. In this case the Invoke Node is used (that is not configurable).

To test such a possibility, I tried to call ActiveX using Call Library Function Node (pointing to the OCX file instead of a DLL) but without any success. Seems that the node can see internal function of the ActiveX but the VI is still broken reporting that the function does not exist. Probably, an OCX file cannot be accessed using Call Library Function Node.

Link to post

Actually, that thread does answer the question. The fundamental issue is that the ActiveX calls are done in the UI thread. Once you take this into account, the results you are seeing are exactly what should be happening, and there's no mystery. If your ActiveX component doesn't have a user interface then you may be able to use an MTA model with a wrapper DLL that can be configured in terms of which thread to use per call.

Link to post

Thank you, Saverio. Indeed, the thread points that the ActiveX is executed in UI thread. Unforttunately, this is not a new or helpfull information.

I cannot wrap the ActiveX inside a DLL because the actual ActiveX is a "third-party product". The ActiveX(-es) that are considered in my examples are created only for these tests.

So, I need to find some trick around this LabVIEW limitation. The limitation certainly belongs to LabVIEW. A simple non-LabVIEW program (I did it with "good-old" VB6) shows that instances of the same ActiveX work asynchronously even if their UI-s are used.

Link to post

I'm not aware of any "trick" to change how LabVIEW calls ActiveX code. Nor am I aware of any "trick" to change the thread model of an already built ActiveX component.

Edited by Saverio
Link to post

I cannot wrap the ActiveX inside a DLL because the actual ActiveX is a "third-party product". The ActiveX(-es) that are considered in my examples are created only for these tests.

So, I need to find some trick around this LabVIEW limitation. The limitation certainly belongs to LabVIEW. A simple non-LabVIEW program (I did it with "good-old" VB6) shows that instances of the same ActiveX work asynchronously even if their UI-s are used.

I don't understand why you can't wrap the ActiveX component. Obviously you got it to behave as desired in your VB6 code, so just crank that code out as a stand-alone DLL and use the CLN to call that from LabVIEW. If you need to support multiple sessions/references/etc, you may have to do some fancy footwork in the VB code, but it should be relatively trivial.

Link to post

This isn't making sense to me. Each ActiveX object defines whether it is an STA or MTA model. LabVIEW is supposed to honor that. If it is STA, we make all calls from our UI thread. If it is MTA, then we allow the calls to happen in any thread. If your object is really MTA and the VI is not set to run in the UI thread, I would expect these calls to happen in parallel. Also your references are named UserControl. All ActiveX controls are STA by definition because all ActiveX UI is STA. If the object is STA, then you shouldn't have been able to run the code in parallel in VB either. Is it true that the ActiveX code is built as a control? Did you use the exact same methods in VB to see the parallel execution or were you calling something similar that really use MTA?

Link to post
asbo: as desired in your VB6 code, so just crank that code out as a stand-alone DLL
GregR: Did you use the exact same methods in VB to see the parallel execution

Sorry, I probably did not write clearly.

The ActiveX is not my. It is a "black box" for me. To my knowledge, it is written in C++. But I have it "as is"; i.e. an OCX file compiled and registered in Windows. So, converting it to DLL is out of question.

The simple VB code is my but it was created only for these tests. The reason for the difference is simple: even after 10 years or so I can recall programming in VB6 but I newer used C++ :wacko:

I did not change anything in settings when created the simplest ActiveX in VB6 but, outside of LabVIEW, its instances work asynchronously. Seems the default model is MTA.

What happend if you call the reentrent VI as a normal Sub-VI, instead of using "Call by reference"?

As I understand, you ask about the last example. The ActiveX calling Invoke Node does not pause the whole program. If I do not use Invoke Node in the bottom structure, there would not be any delay.

Link to post

As I understand, you ask about the last example. The ActiveX calling Invoke Node does not pause the whole program. If I do not use Invoke Node in the bottom structure, there would not be any delay.

What happen if you use two reentrent sub-vi and call them at same time?

//Ulf

Link to post

Actually, I solved the problem. Found a way around. Quite around :D

But first:

What happen if you use two reentrent sub-vi and call them at same time?

If no ActiveX is involved, the Invoke Nodes work asynchronouusly without any problem. This includes parallel cals of a reentrant sub-VI.

Now the solution:

  • The program is split in separate programs communicating with each other. For this test, I used Shared Variables but this is only a test.
  • Each part/program contains only one instance of the ActiveX and performs all tasks related to this instance.

Of course, such a solution does not solve the problem at all. Calls to the ActiveX from independently started VI-s wait for each other.

Now - the trick:

Each part is compailed in an independant EXE file. The EXE-s can be started simultaneously but they are in different "virtual spaces". So, instances of the ActiveX have no idea about each other and the problem is gone. :yes:

Now I shall find how to start several copies of the same EXE program (by default, the LabVIEW compiled EXE allows only one instance). But this is a minor question. At at least, several copies can be started applying Ctl-C Ctl-V to the ready EXE file :)

Link to post

"allowmultipleinstances=true" in the ini file for the exe will do what you want. I still don't understand how the same OCX would allow parallelism in VB but perhaps that is not important if you're happy with this other solution.

Link to post
"allowmultipleinstances=true" in the ini file

Thank you.

I still don't understand how the same OCX would allow parallelism in VB but perhaps that is not important if you're happy with this other solution.

I do not understand too. As a fact, it was very difficult to recall even simple steps in VB6; do not mention about its internnal behaviour.

I am not so terribly happy with the solution. It obviously adds lot of work at the development step. But ... this solution is better than no solution :yes:

Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Similar Content

    • By Gab
      Hello,
      Is it possble to put signatureline into excel footer using Active X ?
    • By Christian Butcher
      Firstly, I'm reposting from the NI Forums here: Programatically reinsert an ActiveX Container
      TL;DR: My goal is to programmatically carry out whatever happens when I right click on an ActiveX container and choose the option 'Insert ActiveX Object...'. Ideally, I would like to avoid using VI Scripting to do this, but I haven't gotten anywhere so far and so really any solution will be a step forwards.
      My most recent attempt (I'm using NI's Actor Framework) has been to place the ActiveX container on an Actor Core panel, then use Pre-Launch Init to open a Static VI Reference, and resize the front panel, with the container set to scale with the front panel. This doesn't work, because the static reference doesn't refer to the same thing that the AF then opens using the Launch Actor VI, but ignoring that problem, it also doesn't help with resizing the container.
      Previously, I manually resized the container, but this I could only do after it was in existence, and so the object was already inserted.
      My current observation seems to be that after I choose the ActiveX object to insert, there is little/nothing I can do to change the size of the object (I can change the container, but this doesn't do anything to the object - probably the object isn't very friendly-ly coded, but I can't do anything about that...). Consequently, I come back to my goal, which is to call some Invoke Node or similar, to 'Insert ActiveX Object...'.
      Is there some way to do this? I don't intend to do it often, so long execution times, recompilation of VIs, shooting a cow over the moon are all fine if needed.
    • By piZviZ
      Our client having Scada based exe application (Non LabVIEW exe.).This application gives popup for saving pdf report file,So they need to write name of report every time.They don't have source code of this application.Now, they want to do automation in this. Whenever this application gives pop up for report name  it should be automatically name by external labview application.
      How it is possible using ActiveX?How to create ActiveX object for this Scada based exe? or any other ways to do this things are most welcomes .
       
    • By peter_flores
      Hello world!
      I am having a very strange issue controlling MS Excel through ActiveX from LabVIEW. I feel like it is likely not a rare task yet I find little to no helpful documentation from the MS side or NI side :/ I am a CLD and am working this project with a CLA and it has cost us over 40 hours of painstaking troubleshooting so far! I hope you can help. Here it goes...
      I am using the following setup: Windows 7 Pro LabVIEW 2015 SP1 Office 2016   I have created a simple LV class to create excel reports which works without an issue on my computer. The problem occurs when I run the code on another PC - Excel crashes ("2016-12-06_1125") and needs to restart, and usually then feeds an error back to LabVIEW("2016-12-06_1152"). This crash is asynchronous to the LabVIEW calls, meaning that a different VI will report the error each time. The problem occurs in Dev Environment and as an EXE.   I have been developing and validating on these two separate systems during the last 3 months of building this project without an issue. The only difference between systems has arisen with the Excel automation. I have now run the project on 5 or 6 machines where 2 exhibit the problem repeatedly. On the rest, I have seen the behavior, but remedy it by updating the ActiveX reference as described below.     Other systems: Works: Win 7, LabVIEW 2015 SP1, Office 2013, .NET 4.6.1;           Win 10, Office 2016, LabVIEW 2015 SP1, .NET 4.6.2 Does not work: Win 10 (.NET 4.6.2), LabVIEW 2015 SP1, Office 2016;     Win 10, LabVIEW 2015 SP1, .NET 4.6.1, Office 2016   "Version 1.3"   A strange behavior that must be related, but I have not been able to exactly correlate it with good or bad behavior is shown in the other two screenshots attached. "Version 1.9" shows the .NET library that should be selected. Occasionally, this appears as shown in "Version 1.3", which looks like garbage - it is hard to tell what library that eve is supposed to be and why it would switch on it's own. We have tried setting this as a constant, control, typedef, with no luck in locking it down and keeping the "Version 1.3" behavior at bay.   Related Post? In doing a lot of googling and research, I have not seen much info on this. Though this post looks like it is describing a similar behavior, though not exactly the same.    Thank you in advance for your help! This is holding up delivery of a $50k LabVIEW job that is scheduled to be delivered by Dec 15 and is looking unlikely because of this bug/anomaly, please help! (you know, the last 10% rule, ahhhh!)  



    • By Erbin
      Hi guys,
      I want to use Vi to format convertion, that .mht to .xlsx of Excel, or .html to .xlsx of Excel, Input path of file, output path of .xlsx.
      I try to  find active X to realize the target, but I can not find.
      I don't know what to do.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.