Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Calling .net dll in Labview

Hi,

 

I am new to C#. I have a C# .net dll with a Form and a ShowForm() function to display the Form. I can call the ShowForm() function from Labview and display the Form without problem.

 

Now I add a NI Vision control (CWIMAQ, a .net component) to the Form, rebuild it. Then It doesn't work any more in Labview. The error msg was: "he ActiveX-Control adbf7240-2b8d-11d1-b5c5-00a024d63828 cannot instantiate, the current Thread is not Singlethread-Apartment"

 

ShowForm()

{

      Form1 myForm = new Form1();

      myForm.show();

 

Any one can help with this error?

 

thanks and best regards

0 Kudos
Message 1 of 9
(11,253 Views)

Hello,

The reason that you recieve this error is that your CWImaq control is actually an ActiveX control, which requires that the thread that loads it is coinitialized as a single-threaded apartment (STA) thread. However, by default, the Labview VI's thread are coinitialized as a Multi-threaded apartment thread.  There are two options you can pursue to relieve this error you are seeing.  One is to change the preferred execution model of your VI to the User Interface.  This can be done from within the VI properties, as shown below:

 

 

 

Alternatively, you could modify your C# code to create and show the form in a STA in a new thread.  A very simple implementation of this can be seen below:

public class Class1
    {
        public void ShowForm()
        {
            Thread mySTAThread = new Thread(new ThreadStart(ShowFormUI));
            try
            {
                mySTAThread.SetApartmentState(ApartmentState.STA);
            }
            catch (ThreadStateException ex)
            {
                MessageBox.Show("STA Failed", ex.Message);
            }
            mySTAThread.Start();

        }

        private static void ShowFormUI()
        {
            TestForm myForm = new TestForm();
            myForm.ShowDialog();
        }
    }


Please let me know if you have any questions about anything I've said, or if I can be of any more assistance!

NickB
National Instruments

Message Edited by nickb on 11-04-2008 08:27 AM
Message 2 of 9
(11,243 Views)

Thanks NickB. Your info make good sense. 

 

I have tried both ways.

For the first method, the VI shows the Form until I close the Form, which is what I wanted.

But for the second method, the VI quickly stopped without showing the Form and there is no error.(Or the Form is shown so fast that I cannot see it?).

 

Could you please give me a hand for this problem.

 

best regards.

 

 

0 Kudos
Message 3 of 9
(11,230 Views)

Hello,

 

When trying the second method and it was time to show your form, did you use Form.Show(), Form.ShowDialog(), or Application.Run(myForm)?  My guess is that you used Form.Show().  In this case,Show() is not modal (blocking), and so the function completes as soon as the form is displayed.  Because this function (the thread procedure) has completed, the thread, as well as the form, are scheduled for cleanup.  Thus, you can either use Form.ShowDialog(), or if you do not want the blocking nature of ShowDialog(), you could do something similar to the following:

 

            myForm.Show();
            while (myForm.formOpen)
            {
                Application.DoEvents();
                Thread.Sleep(50);
            }

 

formOpen is a flag you could create that could be set in the FormClosing event.  DoEvents() processes system messages so that your UI remains responsive, and the sleep give the processor some time to rest.  Finally, if it would make architectural sense for this form that you are displaying to be considered its own application, you could also use Application.Run(myForm) instead of Show or ShowDialog.  In this case, Application.Run takes care of all the message handling for you. Please let me know if you have any other questions!

 

NickB

National Instruments 

0 Kudos
Message 4 of 9
(11,225 Views)

Hi NickB,

 

I was using ShowDialog(). For my understanding, ShowDialog() is dialog-mode, which is activating until further actions, like close.

But it doesn't work the way I thought.

 

/////////////////////The code is:////////////////////////////////

 

        public static void ShowForm()

        {

            //same code like you offered.

        }

        private static void ShowFormUI()
        {
            Form1 myForm = new Form1();
            myForm.ShowDialog();
        } 

 

I also tried Application.Run(myForm), still not working.

 

        public static void ShowForm()

        {

            //same code like you offered.

        }

       private static void ShowFormUI()
        {
            Form1 myForm = new Form1();
            Application.Run(myForm); 

        } 

 

I also tried Thread. sleep, make no effort in Labview. 

 

For all the methods, I tried to call in a C# application. All worked in App but neither worked in Labview.

 

 

Please let me know when you have any ideas about it.

 

Thanks for your time and best regards.

 

 

 

 

 

 

 


 

 

0 Kudos
Message 5 of 9
(11,209 Views)

Once again, this is just a guess, but I think you may be closing the reference to the .NET object before you are ready to, thus closing the form.  When you specify that the preferred execution system is the UI, the .NET app runs in the same thread as the UI, and so the VI waits until the form has closed before proceeding to close the reference to the object.  When you do it the other way, you have to keep the reference alive with a loop somewhat similar to the following:

 

 

Finally, one other option you may look at would be creating your own custom control that provides the functionality of this form you are showing, and embedding the custom control in a LabVIEW .NET container, as described here. This way, the .NET controls lives in the UI thread, you have access to all the properties and methods, and you don't have to worry about keeping the reference alive.  One thing to keep in mind here is that LabVIEW does not support the design time dialogs that are provided for configuring the vision ActiveX control, or any other design time dialogs.

 

NickB

National Instruments 

Message Edited by nickb on 11-05-2008 12:39 PM
0 Kudos
Message 6 of 9
(11,201 Views)

Hi,

 

The "keep the reference alive" solution is not working. I am trying to create a .net control to the container. I will let u know, when any result comes out.

 

Thank you for the help.

0 Kudos
Message 7 of 9
(11,185 Views)

Hi nick

 

I have just begun to use LABView. One of my first task is to call a .NET code in my VI. I am using LABView developers suite and my .NET framework is 4.0. The .NET code contains methods to call Vector CANoe and start CANoe measuremnt. It contains no forms. Please help.

 

regards

Sarath

0 Kudos
Message 8 of 9
(8,361 Views)

Hi, nickb,

 

I encounter the similar issue and hope you can give more details.

 

I write a Test Exective dll by C#. and using labview to call the dll. and i use [STAThread] to these form that will prompt at runtime.

Now, at program startup. the userLogin dialog prompt. it works.

and then we load some test step and run.

after finish, we click the menu to login again. but the UserLogin dialog don't prompt and the program does blocked.

 

I change the preferred execution model of the top vi to user interface, and then the userlogin dialog will prompt at anytime and the program don't block.

but it introduces another question. the UI refresh work badly. the UI refresh become slow. 

there are some .net controls in the front panel of the top vi. we use C# code to collect test result and refresh these net controls by C# itself.

and I call the UserLogin function in the top vi.

 

the below is the block diagram of top vi calling userLogin function. and the C# code to call userLogin dialog.

 

I think that there will be two method to improve.

1, add a sub vi to wapper the C# UserLogin function and call the sub vi in the top vi. 

then change the preferred execution model of sub vi to user interface,----> I will have a try.

 

2, modify the C# code.

but i don't have a idea now.

 

Hope you can give me some suggestion.

 

2013-07-05 15 05 21.jpg

 

++++++++++++++++++

public void RunUserLogin(out bool isLogin, out string userID, out bool isAdmin)
{
Thread newThread = new Thread(new ThreadStart(____RunUserLogin));
newThread.SetApartmentState(ApartmentState.STA);
newThread.Start();

newThread.Join();

isLogin = mIsLogin;
userID = mUserID;
isAdmin = mIsAdmin;
}

[STAThread]
public void ____RunUserLogin()
{
UserLogin frm = new UserLogin();

WindowOwner owner = new WindowOwner();
frm.ShowDialog(owner.GetOwner());

frm.GetUser(out mIsLogin, out mUserID, out mIsAdmin);
}

++++++++++++++++++

 

 

0 Kudos
Message 9 of 9
(8,007 Views)