Machine Vision

cancel
Showing results for 
Search instead for 
Did you mean: 

IMAQ: How to use in multithread application c# .Net

Hi,
 
I've build an application in .Net, C#.
Thereby I use the IMAQ functions coming from the ActiveX components provide by NI, via the Ax...interop.dll 's.
I'v Vision 8.0 installed (8.2 acts the same)
 
But as it seems , the activeX components can not be used in multi threaded applications.
 
Does anybody has advise, tips or the solution? I really need this to operate ion multi threaded application.
 
Thanks!
Tom.
 
 
Message 1 of 9
(9,685 Views)

You can call the IMAQ functions from multiple threads, but you need to create an ActiveX wrapper object instance per thread, and then call CreateControl on it to set the OCXState:

AxCWIMAQVision axCWIMAQVision1 = new AxCWIMAQVision();

axCWIMAQVision1.CreateControl();

You need to set the worker thread apartment state to STA to instantiate ActiveX controls in it:

Thread myThread = new Thread(myThreadProc);

myThread.SetApartmentState(ApartmentState.STA);

myThread.Start();

Before the thread exits, call dispose on the IMAQ vision object and then call Thread.CurrentThread.Join(0) to make sure the garbage collector can switch to your thread context for cleanup. CurrentThread.Join(0)  behaves much like Sleep(0), but does message pumping, which is needed since the STA thread has no message pump.  Calling CurrentThread.Join(0) peroidically should also make your thread responsive to Aborts.

So you end up with:

static void myThreadProc()

{

AxCWIMAQVision axCWIMAQVision1 = new AxCWIMAQVision();

axCWIMAQVision1.CreateControl();

// make some calls on axCWIMAQVision1

//...

axCWIMAQVision1.Dispose();

Thread.CurrentThread.Join(0);

}

I hope that helps,

Jamie

 

Message 2 of 9
(9,611 Views)
Hi,
I'm using VB.NET and having problems with multithreading too.

When I call functions from an axCWIMAQVision control from a separate thread, I get a (runtime) error messages saying that the casting of the parameters is not possible:

For example, on this code:
---------------------------------------
Dim EdgeCoordinatesReport As New CWIMAQEdgeCoordinatesReport
Dim EdgeOptions As New CWIMAQEdgeOptions
Dim LineCoordinates As New CWIMAQLines
...
VTool.Rake(SrcImage, SearchArea, CWIMAQRakeScanDirections.cwimaqScanLeftToRight, _
                           EdgeCoordinatesReport, EdgeOptions, CWIMAQEdgeProcesses.cwimaqEdgeProcessFirst, 10, LineCoordinates)
--------------------------------------

I get something like this:

 'System.InvalidCastException'

Unable to cast COM objects of type 'NationalInstruments.CWIMAQControls.CWIMAQRotatedRectangleClass' in types of interface  'NationalInstruments.CWIMAQControls.CWIMAQRegions'. The operation has not been completed because the call QueryInterface on the COM component for the interface with IID '{CA1B0CF0-5ACA-11D1-B615-00A024D63828}' has failed with the follow error message: Interface not supported. (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).


I've tried to create the AxCWIMAQVision control both before starting the thread and after starting the thread but the problem remains.

Using the AxCWMachineVision component give no problems.

I've alse set the apartmentstate of the thread to STA.

Any suggestions?

Tanks.
--
Simone
0 Kudos
Message 3 of 9
(9,378 Views)

Anyone has a solution for how to use IMAQ ActiveX Interop under multi threading ?

 

For my sake, I made a dotNet 2.0 executable with multiple instances of the same form.

Each form having its own message loop. Each form also embed another STA thread that fires continuously some processing on the GUI thread (using form.invoke()   ).

 

When  I use only one form, everything is fine.

When multiple form are used. Only one form works ok. On other form the following code

       AxCWIMAQVision1.MatchPattern2(l_Img_Cam, l_Img_Label, l_Process_MatchOptions, l_Process_MatchReport)

 

generates the exception:      'System.Reflection.TargetInvocationException' s'est produite dans mscorlib.dll

 

 

0 Kudos
Message 4 of 9
(7,113 Views)

I found a way around the multithreading issue: when starting a new thread that will instanciate an IMAQ ActiveX, I added a sleep time of 1000 milliseconds. Don't ask my why or how .... now it works !! 

It is like on the PCI-6518, between writing output leave a period of 5 millisecond otherwise the value you expect to output will never be output !

The VB2005 projects starts with NI_Form

 

Private Sub Form_StartNI_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    For i As Integer = 1 To 3
        Dim t As New Thread(AddressOf m_fThreadProc_HMI_AppRun_Form)
        t.SetApartmentState(ApartmentState.STA)
        t.Start()
        Threading.Thread.CurrentThread.Sleep(1000)
    Next
End Sub

 

' The thread procedure that will soon host the message loop of a New Form
Private Shared Sub m_fThreadProc_HMI_AppRun_Form()
    Dim t As New ProcessingForm
    Application.Run(t)
End Sub

 


In the ProcessingForm:
 

Private Sub ProcessingForm_Form_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load    
 Dim t As New Thread(AddressOf m_fThreadProc)
 t.IsBackground = True
 t.SetApartmentState(ApartmentState.STA)
 t.Start()
End Sub


Private Sub m_fThreadProc()
   Dim l_Delegate2 As New m_Delegate_HMI(AddressOf m_fSimpleHMIjob)
   Dim l_obj() As Object
   while true
        Me.Invoke(l_Delegate1, l_obj)
   end while
end sub

Private Delegate Sub  m_Delegate_HMI()
Private Sub   m_fSimpleHMIjob()End Sub
       ' Here, do some NI IMAQ processing using AxCWIMAQVision1
       '  such as pattern matching, ....
        Threading.Thread.CurrentThread.Sleep(10)
End Sub

0 Kudos
Message 5 of 9
(7,111 Views)

It is working almost OK, except that calling  method of   axCWMachineVision  leads to exception being thrown.

 

I have now one Form launching 2 background STA threads.

Processing works fine, but I don't succeed into sharing/sending processing results with the GUI thread (even through form.invoke).

I can share Images - thats ok,

 

But for example calling:

CWMachineVision1.DrawPatternMatch CWIMAQViewer1.Image.Overlays(1), Report(1), vbBlue

doesn't work and generate an exception.

I tried calling in both background thread and UI thread, without success.

By the way, as soon as the background thread instanciates CWMachineVision object the processing threads throws exception when calling FindPattern() ...

 

I guess it can be a marshalling problem (and I am not good at solving marshalling issue) or an apartment issue.

My next step is to convert the CWIMAQPatternMatchReportItem into a list of Rectangle.

And on the UI thread I will draw manually each element .... one by one   😞  but that should solve it.

0 Kudos
Message 6 of 9
(7,092 Views)

Did you get the chance the try the native .NET API released with Vision Development Module 2009?

 

-Christophe

0 Kudos
Message 7 of 9
(7,063 Views)

The ActiveX implementation is just not multi thread safe. I used seperate exe in order to overcome this one....

Secondly Vision in Labview seem to be multithreaded as well.

 

The new .net API shoould overcome all of this.(NI confirm this to me) But never tried it. Would be interesting to know if this works....

 

 

 

0 Kudos
Message 8 of 9
(7,056 Views)

Thank you both for your answers.

 

Unfortunately the only VDM licence we have is for VDM 8.0.

We moved to Matrox MIL since then. Smiley Sad

NI Viewer is still more user friendly, so one day we might move back to NI Vision

 

BTW (by the way):

it was my mistake; but instancitation AxCWMachineVision on a thread works fine after you call the function .CreateControl (as stated in this post).

An exception is generated. A try / catch block gets over it !

To me, now it seems that you can do multi threading with the VDM8.2 ActiveX !!

0 Kudos
Message 9 of 9
(7,030 Views)