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 comment

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 comment

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 comment

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 comment

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 comment

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 comment
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 comment

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 comment

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 comment
"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 comment

Join the conversation

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

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
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.

×
×
  • Create New...

Important Information

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