473,804 Members | 2,758 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

MultiThreading an ActiveX DLL call...

Hello,

Is there a good way to call a big time-consumming function from an
ActiveX DLL (interoped) through a thread without blocking the main UI ?

Here are the details :

I have a class CInteropCall encapsulating a call to a visual basic
ActiveX DLL function named FillAlloc_Array Struct_Double() , which is
allocating a big struct array an fills it using a inner loop
(for i = 1 to 300000...)

I'm calling this BigProcess through a thread from the main UI
like this :

CInteropCall MyThreadProcess = new CInteropCall();
Thread m_WorkerThread;
m_WorkerThread = new Thread(new ThreadStart(MyT hreadProcess.Te stMe));
m_WorkerThread. IsBackground = true;
m_WorkerThread. Name = "ThreadLow" ;
m_WorkerThread. Priority = System.Threadin g.ThreadPriorit y.Lowest;
m_WorkerThread. Start();
Here is the TestMe() method from the CInteropCall class which is calling
the function through an instance of a VB6 Class :
public void TestMe()
{
AX_DLL.FillAllo c_ArrayStruct_D ouble(3000000, ref array_struct_do uble);
}
The problem is :
The main UI is blocked when starting the thread, and from time to time
during the thread execution.

Solutions tested :
- adding a Sleep(1) in the inner loop of the vb6 function
It does not change a lot
- adding a DoEvents() in the vb6 function
It does not change a lot but slows down the thread execution.
The same big loop executing from a c# function does not block the main
UI (even without sleep(1)...), the UI remains very smooth.
Any idea to make an interoped vb6 activex call 'UI thread friendly' ?
(or maybe there is no way to do it...)

Regards,
Cybertof.
Nov 17 '05
20 3981
In article <OY************ **@TK2MSFTNGP10 .phx.gbl>,
wi************* @telenet.be says...

"Cybertof" <cy************ @ifrance.com> wrote in message
news:MP******** *************** *@news.wanadoo. fr...
In article <uk************ **@TK2MSFTNGP14 .phx.gbl>,
wi************* @telenet.be says...
Ok, don't mix two different issues, speed and UI responsiveness. Your
initial issue was that the UI thread was blocked for the duration of the
call, the solution for this was to move this to a background thread, right?
Well, is this issue solved?
If it is, we can have a look at the speed issue, a few questions come to
mind though, how's the speed compared to a VB6 client calling into your
object? Could you post some code?

Willy.


Well, the first issue is not totally solved :
Moving the call within a background thread (STA or not) gives more
responsive to the UI, but still blocks it from time to time, which does
occur only at all with the call to the ActiveX DLL Method, so I supposed
there is a thread problem with big arrays beeing passed to an ActiveX,
even if the background thread instanciates the ActiveX Class and calls
it from there.

Let's try to solve the 'Speed problem first' (easier as no background
thread is involved).

Here is some code :

*************** ****
VB6 ACTIVEX DLL : (in a Class named CTest)
*************** ****
Type VBStruct
d As Date
e As Integer
o As Double
h As Double
l As Double
c As Double
v As Long
oi As Long
End Type

Public Sub TestCall(ByRef data() As VBStruct)
MsgBox "FillArrayStruc t_Double : INSIDE AX CALL" // L4
End Sub
*************** *******
C# Test Application : (AX_DLL is the namespace viewed from c#)
*************** *******
AX_DLL.CTest MyTest; // Active X DLL
AX_DLL.VBStruct[] array_struct = null;
MyTest = new AX_DLL.CTest();
startTime = DateTime.Now.Ti cks;
MessageBox.Show ("before alloc...");
array_struct = new AX_DLL.VBStruct[3000000]; // L1
MessageBox.Show ("before ax call"); // L2
AX_DLL.TestCall (ref array_struct_do uble); // L3
MessageBox.Show ("after ax call"); // L5


With this code, 'L1' is immediate to execute,
but, it takes quite some long time to go from
L2->L3->L4, and same long time to go through
L4->L5.

If you replace L1 with
array_struct = new AX_DLL.VBStruct[10]; // L1
everything gets very fast, no wait between calls...

The only cause of the slowness is passing a big array as a parameter.

Do you have an idea ?

Regarding the thread issue, if I put all the C# code above inside a
background STA Thread, the main UI stills blocks approximatively at the
same lines...
Regards,
Cybertof.

Nov 17 '05 #11
Code Update (L3 was wrong)

Please replace

AX_DLL.TestCall (ref array_struct_do uble); // L3

with

MyTest.TestCall (ref array_struct_do uble); // L3

Nov 17 '05 #12

"Cybertof" <cy************ @ifrance.com> wrote in message
news:MP******** *************** @news.wanadoo.f r...
In article <OY************ **@TK2MSFTNGP10 .phx.gbl>,
wi************* @telenet.be says...

"Cybertof" <cy************ @ifrance.com> wrote in message
news:MP******** *************** *@news.wanadoo. fr...
> In article <uk************ **@TK2MSFTNGP14 .phx.gbl>,
> wi************* @telenet.be says...

Ok, don't mix two different issues, speed and UI responsiveness. Your
initial issue was that the UI thread was blocked for the duration of the
call, the solution for this was to move this to a background thread,
right?
Well, is this issue solved?
If it is, we can have a look at the speed issue, a few questions come to
mind though, how's the speed compared to a VB6 client calling into your
object? Could you post some code?

Willy.


Well, the first issue is not totally solved :
Moving the call within a background thread (STA or not) gives more
responsive to the UI, but still blocks it from time to time, which does
occur only at all with the call to the ActiveX DLL Method, so I supposed
there is a thread problem with big arrays beeing passed to an ActiveX,
even if the background thread instanciates the ActiveX Class and calls
it from there.

Let's try to solve the 'Speed problem first' (easier as no background
thread is involved).

Here is some code :

*************** ****
VB6 ACTIVEX DLL : (in a Class named CTest)
*************** ****
Type VBStruct
d As Date
e As Integer
o As Double
h As Double
l As Double
c As Double
v As Long
oi As Long
End Type

Public Sub TestCall(ByRef data() As VBStruct)
MsgBox "FillArrayStruc t_Double : INSIDE AX CALL" // L4
End Sub
*************** *******
C# Test Application : (AX_DLL is the namespace viewed from c#)
*************** *******
AX_DLL.CTest MyTest; // Active X DLL
AX_DLL.VBStruct[] array_struct = null;
MyTest = new AX_DLL.CTest();
startTime = DateTime.Now.Ti cks;
MessageBox.Show ("before alloc...");
array_struct = new AX_DLL.VBStruct[3000000]; // L1
MessageBox.Show ("before ax call"); // L2
AX_DLL.TestCall (ref array_struct_do uble); // L3
MessageBox.Show ("after ax call"); // L5


With this code, 'L1' is immediate to execute,
but, it takes quite some long time to go from
L2->L3->L4, and same long time to go through
L4->L5.

If you replace L1 with
array_struct = new AX_DLL.VBStruct[10]; // L1
everything gets very fast, no wait between calls...

The only cause of the slowness is passing a big array as a parameter.

Do you have an idea ?

Regarding the thread issue, if I put all the C# code above inside a
background STA Thread, the main UI stills blocks approximatively at the
same lines...
Regards,
Cybertof.


Eek!!, an array of 3000000 structs (UDT in VB), I thought you were talking
about doubles. Not suprisingly it takes some time to call a method what did
you expect?

Your array takes 3M * 48 bytes ~140MB managed memory + the same amount
because it must be marshaled to unmanaged memory. That means ~300MB of
Memory taken by this single array.
If you don't have that amount free RAM - and I guess THAT'S YOUR PROBLEM,
the system will start trashing, and the time to marshal the call can tens of
seconds maybe minutes. Even if you have that amount of memory free, it will
take several seconds maybe ten to marshal.
I'm not clear why you need to pass such amount of data between managed and
unmanaged world, but this is not the best solution anyway.

Willy.


Nov 17 '05 #13
In article <u7************ *@TK2MSFTNGP10. phx.gbl>,
wi************* @telenet.be says...

Eek!!, an array of 3000000 structs (UDT in VB), I thought you were >> talkingabout doubles. Not suprisingly it takes some time to call a method what
did
you expect? Your array takes 3M * 48 bytes ~140MB managed memory + the same amount
because it must be marshaled to unmanaged memory. That means ~300MB of
Memory taken by this single array.
If you don't have that amount free RAM - and I guess THAT'S YOUR > PROBLEM,the system will start trashing, and the time to marshal the call can > tens ofseconds maybe minutes. Even if you have that amount of memory free, it
will
take several seconds maybe ten to marshal.
I'm not clear why you need to pass such amount of data between managed
and
unmanaged world, but this is not the best solution anyway.

Willy.

Willy,

Thanks for your answer.

3000000 was for exagerating the test, because I have also noticed some
slowness in smaller arrays.
Ok for the speed needed, but why does it block the main UI Thread even
when the c# is in a backgroud STA thread ?

The idea of the background thread is not to slow the UI, even with a
long task duration (like this one).

In this case, the code is launched from the main UI Thread :

Thread m_WorkerThread;
m_WorkerThread = new Thread(new ThreadStart(MyT hreadProcess.Te stMe));
m_WorkerThread. IsBackground = true;
m_WorkerThread. Name = "ThreadNorm al";
m_WorkerThread. ApartmentState = System.Threadin g.ApartmentStat e.STA;
m_WorkerThread. Priority = System.Threadin g.ThreadPriorit y.Normal;
m_WorkerThread. Start();

(MyThreadProces s is an instance of a class making the call in my
previous code, through the TestMe method)

If I put a lower priority, it does not change, from time to time, the
main UI Thread still blocks...
Christophe.

Nov 17 '05 #14

"Cybertof" <cy************ @ifrance.com> wrote in message
news:MP******** *************** *@news.wanadoo. fr...
In article <u7************ *@TK2MSFTNGP10. phx.gbl>,
wi************* @telenet.be says...

Eek!!, an array of 3000000 structs (UDT in VB), I thought you were >>

talking
about doubles. Not suprisingly it takes some time to call a method what
did
you expect?

Your array takes 3M * 48 bytes ~140MB managed memory + the same amount
because it must be marshaled to unmanaged memory. That means ~300MB of
Memory taken by this single array.
If you don't have that amount free RAM - and I guess THAT'S YOUR >

PROBLEM,
the system will start trashing, and the time to marshal the call can >

tens of
seconds maybe minutes. Even if you have that amount of memory free, it
will
take several seconds maybe ten to marshal.
I'm not clear why you need to pass such amount of data between managed
and
unmanaged world, but this is not the best solution anyway.

Willy.

Willy,

Thanks for your answer.

3000000 was for exagerating the test, because I have also noticed some
slowness in smaller arrays.
Ok for the speed needed, but why does it block the main UI Thread even
when the c# is in a backgroud STA thread ?

The idea of the background thread is not to slow the UI, even with a
long task duration (like this one).

In this case, the code is launched from the main UI Thread :

Thread m_WorkerThread;
m_WorkerThread = new Thread(new ThreadStart(MyT hreadProcess.Te stMe));
m_WorkerThread. IsBackground = true;
m_WorkerThread. Name = "ThreadNorm al";
m_WorkerThread. ApartmentState = System.Threadin g.ApartmentStat e.STA;
m_WorkerThread. Priority = System.Threadin g.ThreadPriorit y.Normal;
m_WorkerThread. Start();

(MyThreadProces s is an instance of a class making the call in my
previous code, through the TestMe method)

If I put a lower priority, it does not change, from time to time, the
main UI Thread still blocks...
Christophe.


Again, I guess your COM object runs on the UI thread. Changing the priority
makes no sense, the CLR doesn't care about it when marshaling between
threads.
Beware if you create the instance of the COM object in MyThreadProcess
constructor, you are effectively creating an instance on the UI thread.
Please post your thread procedure or better the MyThreadProcess , the part
that creates the thread doesn't tell where you create an instance of the COM
object.
Also needed are some figures like your OS and memory size, framework
version...

Willy.


Nov 17 '05 #15
In article <ej************ **@TK2MSFTNGP12 .phx.gbl>,
wi************* @telenet.be says...
Beware if you create the instance of the COM object in MyThreadProcess
constructor, you are effectively creating an instance on the UI thread.
Willy,



You were right....the instanciation of the ActiveX was done in the
constructor, so in the main UI !
I have moved the instanciation to the method, and now it's better.

Last question :
How do you release memory allocated like this :
array_struct = new AX_DLL.VBStruct[3000000];

Is
array_stuct = null;
enough with the marshalling ?

I have tried to call a GC.Collet() inside the thread before it
terminates, but GC.Collet() does not seem to run into the background
thread, does it ?
Regards,
Cybertof.
Nov 17 '05 #16

"Cybertof" <cy************ @ifrance.com> wrote in message
news:MP******** *************** @news.wanadoo.f r...
In article <ej************ **@TK2MSFTNGP12 .phx.gbl>,
wi************* @telenet.be says...
Beware if you create the instance of the COM object in MyThreadProcess
constructor , you are effectively creating an instance on the UI thread.
Willy,



You were right....the instanciation of the ActiveX was done in the
constructor, so in the main UI !
I have moved the instanciation to the method, and now it's better.

Last question :
How do you release memory allocated like this :
array_struct = new AX_DLL.VBStruct[3000000];

Is
array_stuct = null;
enough with the marshalling ?

I have tried to call a GC.Collet() inside the thread before it
terminates, but GC.Collet() does not seem to run into the background
thread, does it ?
Regards,
Cybertof.


Yes,
array_stuct = null;
GC.Collect();
forces a GC run and frees the memory taken by the array_stuct, with such
large structs one of the legitime uses of GC.Collect(). What makes you think
it doesn't run on the background thread?
When done with the COM object your should call Marshal.Release ComObject(...)

Willy.




Nov 17 '05 #17
In article <eN************ **@TK2MSFTNGP12 .phx.gbl>,
wi************* @telenet.be says...
Yes, array_stuct = null;
GC.Collect();
forces a GC run and frees the memory taken by the array_stuct, with such
large structs one of the legitime uses of GC.Collect(). What makes you think
it doesn't run on the background thread?
When done with the COM object your should call Marshal.Release ComObject(...)
Willy.

Thanks for the hint about the Marshal.Release ComObject(...).

What made me think it does not run on the background thread is :
If I put the GC.Collect() on the big array, it slows down the main UI.
If I remove the GC.Collect(), the main UI is not affected.

Does it sound correct to you ?

GC.Collect() is a static method, not instancied within a thread, so
where does it execute ? It 'touches' all orphelin memory parts, from all
threads within the main process ?
Cybertof.
Nov 17 '05 #18
Willy ? are you here ?
Nov 17 '05 #19
If you open up mscorlib.dll with ILDASM and look at GC.Collect() you will see
it eventually gets to the private method GC.nativeCollec tGeneration(). You
will see that this is marked with the pseudoattibute "internalca ll" and that
the actual code of it is blank. This is because the Collection occures within
the .NET Runtime itself and not anywhere in your code.

However, it still poses a bigger threat. Since GC works with "generation s",
whenever Garbage Collection occures, the entire Runtime for that application
will pause during collection, reguardless of threads. I would recommend
setting what you don't need as null, but don't call collection. When GC does
happen on it's own and it sees that it is null, it won't hesitate to collect
it.

Another factor about collection is resurrection. Resurrection is exactly as
it sounds. When an application is no longer accessing a live object, the
garbage collector considers the object to be dead. However, if the object
requires finalization, the object is considered live again until it is
actually finalized, and then it is permanently dead. In other words, an
object requiring finalization dies, lives, and then dies again. When the
object is going to be finalized, avoid multiple resurections, or worse, a
loop where the object is called for finalization, resurrected, and then set
for finalization again, then finalized, so it get's stuck.

Be careful when working with static or global objects as well. Something
like this would hurt:

public class BaseObj {

~BaseObj() {
Application.Obj Holder = this;
}
}

class Application {
public static Object ObjHolder; // Defaults to null
....
}

Note about how GC works in the Framework, objects that are 20,000 bytes or
larger are placed on a special heap. This is transparent so the developer nor
the actual code itself will know it. As far as it is concerned, it is one
heap. The reason for this is the special heap is never compacted. Shifting
20,000 bytes or more down the heap will require too much CPU time.

Generally I would recommend not calling collection on your own unless you
have very good reasons.

"Cybertof" wrote:
In article <eN************ **@TK2MSFTNGP12 .phx.gbl>,
wi************* @telenet.be says...
Yes, array_stuct = null;
GC.Collect();
forces a GC run and frees the memory taken by the array_stuct, with such
large structs one of the legitime uses of GC.Collect(). What makes you think
it doesn't run on the background thread?
When done with the COM object your should call Marshal.Release ComObject(...)
Willy.

Thanks for the hint about the Marshal.Release ComObject(...).

What made me think it does not run on the background thread is :
If I put the GC.Collect() on the big array, it slows down the main UI.
If I remove the GC.Collect(), the main UI is not affected.

Does it sound correct to you ?

GC.Collect() is a static method, not instancied within a thread, so
where does it execute ? It 'touches' all orphelin memory parts, from all
threads within the main process ?
Cybertof.

Nov 17 '05 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

15
9735
by: Mark Sisson | last post by:
Hey all. I've got a legacy COM dll that I'd like to use in my multithreaded C# app. Problem though is when I create several instances of the interop object and start them on their own threads they always seem to run synchronously. I've boiled down the code to a simple "lab" experiment below. In this console app you'll see that instance one comes back after roughly 4 seconds and then instance two comes back in 8 seconds, twice the...
1
3404
by: Marwan | last post by:
Hello I am using asynchronous delegates to make a call to a COM ActiveX object, but even though the call occurs on a separate thread, my UI is still blocking. If i put the thread to sleep in my delegate call, the application is well behaved (no UI freeze), but the call to the com object causes the UI to lock up Do I have to manage calls to an ActiveX object differently than using the BeginInvoke and a callback A sample of the code I...
3
3142
by: Ed | last post by:
Here's my situation, I am moving some of my apps over from native C++ (primarily Win32 and MFC). One of these apps uses some COM objects in worker threads running in the background where it doesn't bother the user. I'm keeping the native code that interfaces with the COM objects in a DLL since I know it works with no problem (I've used for a year and half with no bugs).
11
4274
by: Mark Yudkin | last post by:
The documentation is unclear (at least to me) on the permissibility of accessing DB2 (8.1.5) concurrently on and from Windows 2000 / XP / 2003, with separate transactions scope, from separate threads of a multithreaded program using embedded SQL. Since the threads do not need to share transaction scopes, the sqleAttachToCtx family of APIs do not seem to be necessary. <quote> In the default implementation of threaded applications against...
9
2466
by: tommy | last post by:
hi, i have found a example for multithreading and asp.net http://www.fawcette.com/vsm/2002_11/magazine/features/chester/ i want to speed up my website ... if my website is starting, they should build a database-connection and send a few sqls
2
3741
by: shonend | last post by:
**** sorry about the length of the message. If you can't read the whole thing and still willing to help, read the last 2 paragraphs where the main problem is described. The introduction story is mentioned to, as much clear as possible, give a picture in what environment the problems rise**** Hello experts! I would appreciate if you can address this problem I have and give a hint what could be wrong.
5
5707
by: Yeti | last post by:
Hey everyone, I am modifying code upgraded from VB 6 to 2005. I need to run the 2005 code in the MTA mode so I set a sub main procedure in my module which runs first when the program starts: Public theApplicationForm As New Form1 <MTAThread()> Public Sub main() Application.Run(theApplicationForm) End Sub
4
2674
by: boo73uk | last post by:
Hi All, I'm going to rewrite a VB6 app to VB.net and I need some pointers. Basically this app spawns simultaneous,multiple, independant ActiveX.exe 'workers' which query a SQL Server database and BCP a load of data out. Now, what is the best way to approach this in .Net? Can .Net give me a better way of utilising the resources of the server? We're also getting some new hardware, 2 CPU Xeon rig with HT (hyper threading). Are there any...
2
2271
by: Pradnya Patil | last post by:
hi , I am trying to draw ' html div-tag ' on the screen which will resemble a rectangle through vb.net code. I want it to be drawn faster...so I introduced multithreading using Threadpool. I divided the complete drawing into 3 parts..1st will be done by main thread and other two are done in these procedures - <1LongTimeTask <2LongTimeTask2 I have invoked the threads using below method. **************
0
9576
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10323
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10311
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10074
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
6847
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5516
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5647
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3813
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2988
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.