Jump to content

Dll Thread calling


Recommended Posts

Hi

I try to write a software using Labjack library ( http://labjack.com/support/ud/examples/labview ).

This library made dll calling. When i look the call library function node configuration, i see than the calling is on "Run in UI thread" and not "Run in any thread".

Can you explain me the difference between "Run in UI thread" and "Run in any thread".

Who is best when i made few calling in same time and speedily. I try to work with 5 Labjack U9E in same time.

Actually when run my software, it take 50% CPU time.

Eric

Link to comment

Forcing the library to run in the UI thread isn't good for multiple callers because all your callers are waiting to use the same resource, but may be necessary for the work the library is doing. You could try a different thread setting (use any thread would use any LV thread that's available) but don't hold me responsible if something catches fire :P

Link to comment

The difference is whether the DLL is "Thread Safe" or not. Orange means it runs in a single thread (the UI Thread and there is only 1). Nicotine coloured and it can be run in any thread that LV decides it wants too.

It's best to use the UI thread if you are not sure. Side effects can be anything from crashes, strange behaviour, or erroneous calculation errors under certain conditions.

Link to comment

Hi

I try to write a software using Labjack library ( http://labjack.com/s...xamples/labview ).

This library made dll calling. When i look the call library function node configuration, i see than the calling is on "Run in UI thread" and not "Run in any thread".

Can you explain me the difference between "Run in UI thread" and "Run in any thread".

Who is best when i made few calling in same time and speedily. I try to work with 5 Labjack U9E in same time.

Actually when run my software, it take 50% CPU time.

Eric

From the LabVIEW help

Configuring for Multiple Thread Operation

In a multithreaded operating system, you can make multiple calls to a DLL or shared library simultaneously. You can select the thread to execute the library call from the Thread section on the Function tab of the Call Library Function dialog box. The thread options are Run in UI thread and Run in any thread. If you select Run in UI thread, the Call Library Function Node switches from the thread the VI is currently executing in to the user interface thread. If you select Run in any thread, the Call Library Function Node continues in the currently executing thread. By default, all Call Library Function Nodes run in the user interface thread.

Before you configure a Call Library Function Node to run in any thread, make sure that multiple threads can call the function simultaneously. In a shared library, code can be considered thread-safe when:

* It does not store any global data, such as global variables, files on disk, and so on.

* It does not access any hardware. In other words, the code does not contain register-level programming.

* It does not make any calls to any functions, shared libraries, or drivers that are not thread safe.

* It uses semaphores or mutexes to restrict access to global resources.

* It is called by only one non-reentrant VI.

Note All calls to LabVIEW-built shared libraries should specify Run in any thread. If you configure the Call Library Function Node using LabVIEW-built shared libraries and specify Run in UI thread, LabVIEW might hang and require you to restart.

So, if the LabJack guys distribute a VI that calls their DLL with the Run in UI Thread checked, maybe they know it isn't thread safe. You could always try, but don't be surprised if there's a major crash :)

And if it will run in any thread, then you might want to consider increasing the execution systems setting (I think that's the correct terminology) in LabVIEW to five, since each DLL call will consume a thread and with the default four threads per processor, one call might have to wait. Unless you have dual-core machine, then you already have 8 execution systems.

Mark

Shaun's faster than I am :)

  • Like 1
Link to comment

After search in Labjack documentation i have find this :

"

4.1.2 Multi-Threaded Operation

This driver is completely thread safe. With some very minor exceptions, all these functions can be called from multiple threads at the same time and the driver will keep everything straight. Because of this Add, Go, and Get must be called from the same thread for a particular set of requests/results. Internally the list of requests and results are split by thread. This allows multiple threads to be used to make requests without accidentally getting data from one thread into another. If requests are added, and then results return LJE_NO_DATA_AVAILABLE or a similar error, chances are the requests and results are in different threads.

The driver tracks which thread a request is made in by the thread ID. If a thread is killed and then a new one is created, it is possible for the new thread to have the same ID. Its not really a problem if Add is called first, but if Get is called on a new thread results could be returned from the thread that already ended.

As mentioned, the list of requests and results is kept on a thread-by-thread basis. Since the driver cannot tell when a thread has ended, the results are kept in memory for that thread regardless. This is not a problem in general as the driver will clean it all up when unloaded. When it can be a problem is in situations where threads are created and destroyed continuously. This will result in the slow consumption of memory as requests on old threads are

left behind. Since each request only uses 44 bytes, and as mentioned the ID's will eventually get recycled, it will not be a huge memory loss. In general, even without this issue, it is strongly recommended to not create and destroy a lot of threads. It is terribly slow and inefficient. Use thread pools and other techniques to keep new thread creation to a minimum. That is what is done internally.

The one big exception to the thread safety of this driver is in the use of the Windows TerminateThread() function. As is warned in the MSDN documentation, using TerminateThread() will kill the thread without releasing any resources, and more importantly, releasing any synchronization objects. If TerminateThread() is used on a thread that is currently in the middle of a call to this driver, more than likely a synchronization object will be left open on the particular device and access to the device will be impossible until the application is restarted. On some devices, it can be worse. On devices that have interprocess synchronization, such as the U12, calling TerminateThread() may kill all access to the device through this driver no matter which process is using it and even if the application is restarted. Avoid using TerminateThread()! All device calls have a timeout, which defaults to 1 second, but can be changed. Make sure to wait at least as long as the timeout for the driver to finish.

"

Can you agree that i can modify UI tread option to Any thread option.?

Link to comment

After search in Labjack documentation i have find this :

"

<snip>

"

Can you agree that i can modify UI tread option to Any thread option.?

I would say (tentatively) no.

It says "Because of this Add, Go, and Get must be called from the same thread"

If you set the nodes to any thread you cannot gurantee that that won't happen since you don't know (from call to call) what will run in what thread. So Add might be in one, while Get might be in another depending on what labview feels like doing.

Edited by ShaunR
Link to comment

I have to agree with Shaun. While the text may seem to indicate that the driver is MOSTLY thread safe, it isn't completely. The three mentioned calls need to be made from the same thread and the only way to easily guarantee that in LabVIEW is by calling them in the UI Thread. And incidentially I would say that are probably also the only functions where you could possibly gain some performance if you could call them multithreaded.

So I would not bother to change the VI library at all.

Link to comment
  • 2 months later...

Hi Guys,

there is one thing that bothers me. I am new to Labview Programming, but I have some experience with c and python especially in hardware programming with cameras and positioners.

Actually I have to acquire images from a 2 cameras and a NidaqAcquisition Card at the same time with labview 2010. Everything is running and working parrallel. But I want to optimize it.

So now if these Hardware DLLs that are controlling the hardware are called all in the same UI Thread, don't they blocade each other? Actually it is slowing down the camera acquisition here a lot.

But if I am reading out one of the cameras in another software, while accessing the other Hardware as usual with Labview the framerate of the camera is much higher and the Hardware-Acquisition in Labview is

much smoother too! So if it works in two different software it should be possible with only one too.

So I think it might be useful to give each DLL-Call the posibility to be called in different threads. And if they are not threadsafe, you can use semaphores to make them be called in the right order and to avoid that

not-threadsafe-functions are not called at the same time?

Or am I wrong. As I've said, I am new in LabView.

ps: Sorry for my weird language, I am not used to discuss in english!

Link to comment

Hi Guys,

there is one thing that bothers me. I am new to Labview Programming, but I have some experience with c and python especially in hardware programming with cameras and positioners.

Actually I have to acquire images from a 2 cameras and a NidaqAcquisition Card at the same time with labview 2010. Everything is running and working parrallel. But I want to optimize it.

So now if these Hardware DLLs that are controlling the hardware are called all in the same UI Thread, don't they blocade each other? Actually it is slowing down the camera acquisition here a lot.

But if I am reading out one of the cameras in another software, while accessing the other Hardware as usual with Labview the framerate of the camera is much higher and the Hardware-Acquisition in Labview is

much smoother too! So if it works in two different software it should be possible with only one too.

So I think it might be useful to give each DLL-Call the posibility to be called in different threads. And if they are not threadsafe, you can use semaphores to make them be called in the right order and to avoid that

not-threadsafe-functions are not called at the same time?

Or am I wrong. As I've said, I am new in LabView.

ps: Sorry for my weird language, I am not used to discuss in english!

Don't worry, your language is quite fine.

DLL functions are only executed in the single threaded UI Execution system, if you set them like that in the Call Library Configuration. Otherwise they are called in whatever thread is currently available for the execution system, the current VI is executing in.

But unfortunately the "Call in single threaded UI context" is not so much to avoid race conditions in the call sequence itself. You can already avoid that by using proper data flow, making sure functions execute sequentially instead of parallel. The issue is much more complicated than that. So could a DLL for instance use thread local storage to store state between function calls. This is a nice way to avoid passing context values between function calls and works perfectly in C, since you typically call a DLL all from the same thread. In LabVIEW this fails miserably since each execution system has a number of associated threads and LabVIEW will pick one of them which is free to call your function in. So not only different functions in your DLL can get called from different (random) threads but also the same function when called multiple times.

So it is not as easy when you deal with DLL function calls. Your DLL may be not thread safe because of using global resources such as variables or hardware , but if you know about that and take care about avoiding race conditions through semaphores or simply proper dataflow there is no real problem in executing the DLL functions from other execution systems than the LabVIEW UI one. Off course this is not an option for a library you are going to distribute simply because it is almost impossible to describe the necessary limitations to most of your potential users but the most advanced ones.

On the other hand your DLL may be so called thread safe but use thread local storage and that makes it almost impossible to call your DLL functions safely from other execution systems than the UI one. And there are various other issues that are complicating the whole topic.

For your case it means you REALLY need to understand what are the requirements of the used DLL in terms of multithreading. UI execution system is the safe one because it avoids all these potential snake pits, but at the cost of serializing any and all calls done in it and therefore quickly causing performance issues. LabVIEW multithreaded calling of DLL functions on the other hand has quite a few potential gotchas but gives you a way of avoiding serialization of functions.

Link to comment

Thanks for the anwer.

I never thinked about Thread-Local-Storage. Seems to be usefull when you are writing a C-Dll!

I took another look what Labview-Help says about the "Call Library Function Dialog Box" when choosing the Thread to "Run in any thread":

"Specifies that the Call Library Function Node execution continues on the current thread executing the VI"

So I made shure that every VI, calling the DLL are running in the same Thread (I choosed "other Thread 1").

It is working, and the DLL-Calls arn't blocading the GUI any more.

Link to comment

Thanks for the anwer.

I never thinked about Thread-Local-Storage. Seems to be usefull when you are writing a C-Dll!

I took another look what Labview-Help says about the "Call Library Function Dialog Box" when choosing the Thread to "Run in any thread":

"Specifies that the Call Library Function Node execution continues on the current thread executing the VI"

So I made shure that every VI, calling the DLL are running in the same Thread (I choosed "other Thread 1").

It is working, and the DLL-Calls arn't blocading the GUI any more.

It's not "Other Thread 1" but "Other 1" execution system really. There is a difference in that since LabVIEW 7.0 or so, an execution system has by default assigned more than one thread each. If your code is truely thread safe and doesn't use TLS then this is no problem at all, but it means that eventhough all your VIs execute in the LabVIEW execution system "Other 1" they may not always run in the context of the same thread but anyone of the 4 or 8 threads assigned to this LabVIEW execution system.

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