NI TestStand

cancel
Showing results for 
Search instead for 
Did you mean: 

Teststand 4.1.1 Crashes when using two or more "run VI Asynchronously" at a time

Solved!
Go to solution

I am running a terminal window reading constantly from a serial port running in a different thread using "Run VI Asynchronously". 

 

Towards the end of the test I open a separate VI in another thread also using "Run VI Asynchronously".  This VI constantly reads packets from the Ethernet.

 

I am running the Sequence in the C++ User interface and for some reason every once in a while TestStand Crashes and in the dialog it it says

 

"MFC Operator interface Example has encountered a problem and needs to close.  We are sorry for the inconvenience."

 

Error signature:

AppName: testexec.exe    AppVer: 4.1.1.55   ModName: msvcr80.dll

 

Do any of you have any idea as to why this would do this?  Also what is the best way to open and close these threads?

 

Any help would be greatly appreciated.

Glenn Ellis
0 Kudos
Message 1 of 15
(5,107 Views)

What parameters are you passing into the VI? Becareful when passing something like Sequence Context as that will really be the sequence context of the thread that created the new VI's thread and that thread will continue running in parallel. If you want the sequencecontext of the new thread passed into the VI, use a sequence call step that calls a subsequence in a new thread instead and put your VI call in that subsequence.

 

Also, you need to be careful when multiple threads are modifying and/or accessing the same data structure. You might need to use a lock to synchronize any access to shared data.

 

Hope this helps,

-Doug

Message Edited by dug9000 on 03-01-2010 10:28 AM
Message 2 of 15
(5,103 Views)

I am passing the sequence context into both VIs.  But they are accessing completly different data, at least from what I am aware.

 

So you are suggesting I call the VIs in a subsequece in a new thread instead of using the "Run VI Asyncronously"?

 

Is that a better way of calling multiple threads?

 

Glenn Ellis
0 Kudos
Message 3 of 15
(5,097 Views)

The sequence context that run vi asynchronously will end up giving you is the sequence context for the sequence in the original thread. This causes a fundamental race condition in that that sequence context is for an asynchronously running thread that might complete and go away before the new thread you created to run the VI even starts. By using the sequence call, new thread option instead and creating a VI in the subsequence you will instead get a sequence context specific to that new thread instead of from the original thread which is a lot safer because it belongs to the thread that will be accessing it.

 

 

What are you using the sequence context for? Please explain what data you are accessing from the sequence context and I can suggest a safer alternative.

 

-Doug

Message Edited by dug9000 on 03-01-2010 11:31 AM
Message 4 of 15
(5,086 Views)

Thanks for your quick response.

 

I am going to try using the vi in a subsequence and see if it solves my issue.  But here is what I am doing.

 

  1. In the setup section of the main sequence I open a Labview terminal that just reads serial data. Here is what is passed into the VI:
    1.  Object reference to a fileglobal string which the vi continually updates.
    2. Sequence context (Used for termination Monitor)
  2. Later on in the main Sequence I run a subsequence and within that Sequence I open a new thread using the run VI asynchronously and here is what I pass into it:
    1. Sequence context (used for a few local variables within the current sequence)
    2. The variables accessed using the sequence context are:
      1. two Boolean reads
      2. 5 numeric writes
      3. the variables are updated in multiple loops running in parallel controlled by queues
    3. The asynchronous VI is stopped and closed in the subsequence.

The VI called in the subsequence is used to test PRBS data received over the Ethernet and it updates the variables in Teststand which are tested for various conditions.

There is a lot going on in the PRBS VI and it is probably the main culprit.  Hopefully running it in it's own sequence my alleviates some of the issues.
Glenn Ellis
0 Kudos
Message 5 of 15
(5,071 Views)

In case 1 below you should definitely be using the sequence context of the new thread rather than the original thread. Using a subsequence (in a new thread) directly is a good idea for that use case.

 

In case 2 are you dynamically/programmatically creating local variables in any of the threads or are you just setting/getting values? Setting and getting values is protected by the TestStand engine, but dynamically creating properties underneath Locals or other containers requires you to do your own thread synchronization (i.e. using locks) around such modifications and access.

 

Also, in case 2 you are using locals from the original thread that creates the new thread right? Is that what you want? It would be safer to pass the actual local variables that you need in this case as parameters rather than passing the sequence context that belongs to a different thread. Also do you start and stop the asynchronous vi in the same subsequence in the same thread? Do you wait for the asynchronous VI to finish before exiting the subsequence?

 

All that run VI Asynchronously does is create a temporary sequence and use the sequence call step to call it in a new thread, so doing that explicitly instead will give you more control over how the parameters are passed so it's probably worth making that change anyway. You might however need to be doing more than that to ensure thread safety depending on what parameters you are passing in and what the VIs and other code in the original thread is doing with them.

 

Hope this helps,

-Doug

0 Kudos
Message 6 of 15
(5,057 Views)

I really appreciate you input it has cleared things up.

 

The answer to case 2 is that I am not dynamically creating local variables. 

The variables used are mainly to send status to TestStand and for teststand to command the VI while it is running.

Also the Sequence context passed is from the sequence the VI is called from.

The VI is Started and stopped in the same subsequence and I do wait for the VI to finish before exiting the subsequence.

 

I put the PRBS VI (VI that is called in the subsequence of the Main) in its own sequence and have it to execute in a new thread.  I have a technician testing it currently and hopefully the crash disappears.

 

So from what you have said previously, it seems to me that it is better to use the sequence to execute in a new thread rather than use the "Run VI Asynchronously" Step type.

 

 

Glenn Ellis
0 Kudos
Message 7 of 15
(5,038 Views)

glennjammin wrote: 

 

So from what you have said previously, it seems to me that it is better to use the sequence to execute in a new thread rather than use the "Run VI Asynchronously" Step type.

 

 


If you want to pass ThisContext into the VI then yes. Also if you want more control over how things work. Basically the Run VI Asynchronously step type really just uses a New Thread sequence call to implement it's behavior, it just passes the parameters you specify from the original sequence's context instead of the New Thread sequence's context.

 

For example, if you use  Run VI Asynchronously and pass ThisContext, what's really happening is that the ThisContext is passed to the New Thread sequence from the original thread's sequence as Parameter to the sequence call step (i.e. Parameter.ThisContext is created in the New Thread's sequence), and then that is passed to the VI. That's a different context (i.e. it's the context of the original thread rather than the new thread) then if you don't use Run VI asynchronously and instead create a new sequence where you specify the VI and pass ThisContext to it (i.e. you are passing the new thread's context in this case rather than the original threads). Sorry if this is a bit confusing, but hopefully I have explained it clearly enough. Let me know if it's still unclear. Hopefully things will work now that you are using the context of the new thread rather than the original thread. Let me know.

 

-Doug

0 Kudos
Message 8 of 15
(5,022 Views)

I just reread what you wrote and want to make sure I have explained the issue correctly as what you are doing might still be unsafe.

 

It's not sufficient to switch to using the New Thread sequence call. You need to stop passing the sequence context from the original thread into the new thread. You can instead pass the specific variables you want to access. For example you could pass Locals.MyVar instead of ThisContext. If you do this then you can still use Run VI Asynchronously too. Basically the idea is, don't pass the context from the original thread into the VI, but individual variables should be ok as long as your are only getting/setting values and not modifying their structure.

 

Hope this helps clear things up,

-Doug

0 Kudos
Message 9 of 15
(5,020 Views)

Thanks for the explination.

 

So how can I update the individual variables while the VI is running and access them in testand at the same time?

Glenn Ellis
0 Kudos
Message 10 of 15
(5,016 Views)