473,386 Members | 1,873 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Thread and COM Interop

Hi All

Does anybody have any ideas what I am doing wrong with this code.

What I am trying to do is read data from a Domino Database. For
purposes of the test I have wrapped the DominoCom object in a C# class
that runs in a seperate thread.

If I run this code:
rd = new ReadData(src, 1, 10, this);
list.Add(rd);

t = new Thread(new ThreadStart(rd.Read));
t.Name = "Thread " + ++ThreadId;
t.Start();

rd = new ReadData(src, 30, 20, this);
list.Add(rd);
t = new Thread(new ThreadStart(rd.Read));
t.Name = "Thread " + ++ThreadId;
t.Start();

rd = new ReadData(src, 100, 30, this);
list.Add(rd);

t = new Thread(new ThreadStart(rd.Read));
t.Name = "Thread " + ++ThreadId;
t.Start();

Which starts three threads it all works as I would expect

but if I do it in a loop (which is what I want to do) the code stops
at the
point where it calls into the Domino COM Class.

list = new ArrayList(10);

while (!isComplete)
{
if (list.Count < 10)
{
rd = new ReadData(src, offset * 10 + 1, docCount, this);
list.Add(rd);

t = new Thread(new ThreadStart(rd.Read));
t.Name = "Thread " + ++ThreadId;
t.Start();

offset++;
rd = null;
t = null;
}
}

What I dont understand is why this should be any different to starting
each thread as per the previous example...

If anybody has any ideas I would be grateful...

Regards

Paul Bowman
Nov 15 '05 #1
3 1932
Paul,

If the COM component is apartment threaded, then you are making the call
to the thread in the wrong way. Apartment-threaded components in COM
require the thread to be set up correctly for proper marshaling between
apartments. .NET code by default doesn't run in an apartment state. You
have to set it explicitly for a new thread.

Because you are passing the Read method in as the thread entry point,
you aren't setting the thread up correctly. What you really need to do, is
before you make any calls to COM on the new thread, is set the
ApartmentState property of the current thread to ApartmentState.STA. This
will ensure that apartment-state COM components are run correctly on that
thread.

However, you might have an additional problem. If the ReadData class
has an instance of an apartment threaded COM object stored in it that you
are referencing with the Read method, then the interface pointer is not
being marshaled correctly across apartments. In this case, no matter what
the apartment is, you require marshaling of that interface pointer. The
reason for this is that the STA in the new thread is different from the STA
in the original thread it was created in (if it was created in an STA
apartment). If the original apartment was MTA, then you still have to
marshal it correctly (in this case, you are marshaling a proxy actually),
but it still has to be done. The common way to do this was through the
Global Interface Table (GIT).

So, if this is the case, then you will have to take the COM reference,
place it on the GIT, and then get it in the thread, after you have
initialized the apartment state.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Paul Bowman" <pa**************@yahoo.co.uk> wrote in message
news:ff**************************@posting.google.c om...
Hi All

Does anybody have any ideas what I am doing wrong with this code.

What I am trying to do is read data from a Domino Database. For
purposes of the test I have wrapped the DominoCom object in a C# class
that runs in a seperate thread.

If I run this code:
rd = new ReadData(src, 1, 10, this);
list.Add(rd);

t = new Thread(new ThreadStart(rd.Read));
t.Name = "Thread " + ++ThreadId;
t.Start();

rd = new ReadData(src, 30, 20, this);
list.Add(rd);
t = new Thread(new ThreadStart(rd.Read));
t.Name = "Thread " + ++ThreadId;
t.Start();

rd = new ReadData(src, 100, 30, this);
list.Add(rd);

t = new Thread(new ThreadStart(rd.Read));
t.Name = "Thread " + ++ThreadId;
t.Start();

Which starts three threads it all works as I would expect

but if I do it in a loop (which is what I want to do) the code stops
at the
point where it calls into the Domino COM Class.

list = new ArrayList(10);

while (!isComplete)
{
if (list.Count < 10)
{
rd = new ReadData(src, offset * 10 + 1, docCount, this);
list.Add(rd);

t = new Thread(new ThreadStart(rd.Read));
t.Name = "Thread " + ++ThreadId;
t.Start();

offset++;
rd = null;
t = null;
}
}

What I dont understand is why this should be any different to starting
each thread as per the previous example...

If anybody has any ideas I would be grateful...

Regards

Paul Bowman

Nov 15 '05 #2
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in message news:<#8**************@TK2MSFTNGP10.phx.gbl>...
Paul,

If the COM component is apartment threaded, then you are making the call
to the thread in the wrong way. Apartment-threaded components in COM
require the thread to be set up correctly for proper marshaling between
apartments. .NET code by default doesn't run in an apartment state. You
have to set it explicitly for a new thread.

Because you are passing the Read method in as the thread entry point,
you aren't setting the thread up correctly. What you really need to do, is
before you make any calls to COM on the new thread, is set the
ApartmentState property of the current thread to ApartmentState.STA. This
will ensure that apartment-state COM components are run correctly on that
thread.

However, you might have an additional problem. If the ReadData class
has an instance of an apartment threaded COM object stored in it that you
are referencing with the Read method, then the interface pointer is not
being marshaled correctly across apartments. In this case, no matter what
the apartment is, you require marshaling of that interface pointer. The
reason for this is that the STA in the new thread is different from the STA
in the original thread it was created in (if it was created in an STA
apartment). If the original apartment was MTA, then you still have to
marshal it correctly (in this case, you are marshaling a proxy actually),
but it still has to be done. The common way to do this was through the
Global Interface Table (GIT).

So, if this is the case, then you will have to take the COM reference,
place it on the GIT, and then get it in the thread, after you have
initialized the apartment state.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Paul Bowman" <pa**************@yahoo.co.uk> wrote in message
news:ff**************************@posting.google.c om...
Hi All

Does anybody have any ideas what I am doing wrong with this code.

What I am trying to do is read data from a Domino Database. For
purposes of the test I have wrapped the DominoCom object in a C# class
that runs in a seperate thread.

If I run this code:
rd = new ReadData(src, 1, 10, this);
list.Add(rd);

t = new Thread(new ThreadStart(rd.Read));
t.Name = "Thread " + ++ThreadId;
t.Start();

rd = new ReadData(src, 30, 20, this);
list.Add(rd);
t = new Thread(new ThreadStart(rd.Read));
t.Name = "Thread " + ++ThreadId;
t.Start();

rd = new ReadData(src, 100, 30, this);
list.Add(rd);

t = new Thread(new ThreadStart(rd.Read));
t.Name = "Thread " + ++ThreadId;
t.Start();

Which starts three threads it all works as I would expect

but if I do it in a loop (which is what I want to do) the code stops
at the
point where it calls into the Domino COM Class.

list = new ArrayList(10);

while (!isComplete)
{
if (list.Count < 10)
{
rd = new ReadData(src, offset * 10 + 1, docCount, this);
list.Add(rd);

t = new Thread(new ThreadStart(rd.Read));
t.Name = "Thread " + ++ThreadId;
t.Start();

offset++;
rd = null;
t = null;
}
}

What I dont understand is why this should be any different to starting
each thread as per the previous example...

If anybody has any ideas I would be grateful...

Regards

Paul Bowman


Hi Nicholas

Thanks for your reply and the info - that was really helpful and
certainly gives me food for thought.

I seem to have corrected the problem by changing the [STAThread] to
[MTAThread] in code. I am not sure if this is the complete answer and
I will research the points you raised.

Once again thanks for your response.

Regards

Paul Bowman
Nov 15 '05 #3
It's hard to tell without knowing the apartment types supported by the COM
object.

Willy.

"Paul Bowman" <pa**************@yahoo.co.uk> wrote in message
news:ff*************************@posting.google.co m...
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote
in message news:<#8**************@TK2MSFTNGP10.phx.gbl>...
Paul,

If the COM component is apartment threaded, then you are making the
call
to the thread in the wrong way. Apartment-threaded components in COM
require the thread to be set up correctly for proper marshaling between
apartments. .NET code by default doesn't run in an apartment state. You
have to set it explicitly for a new thread.

Because you are passing the Read method in as the thread entry point,
you aren't setting the thread up correctly. What you really need to do,
is
before you make any calls to COM on the new thread, is set the
ApartmentState property of the current thread to ApartmentState.STA.
This
will ensure that apartment-state COM components are run correctly on that
thread.

However, you might have an additional problem. If the ReadData class
has an instance of an apartment threaded COM object stored in it that you
are referencing with the Read method, then the interface pointer is not
being marshaled correctly across apartments. In this case, no matter
what
the apartment is, you require marshaling of that interface pointer. The
reason for this is that the STA in the new thread is different from the
STA
in the original thread it was created in (if it was created in an STA
apartment). If the original apartment was MTA, then you still have to
marshal it correctly (in this case, you are marshaling a proxy actually),
but it still has to be done. The common way to do this was through the
Global Interface Table (GIT).

So, if this is the case, then you will have to take the COM
reference,
place it on the GIT, and then get it in the thread, after you have
initialized the apartment state.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Paul Bowman" <pa**************@yahoo.co.uk> wrote in message
news:ff**************************@posting.google.c om...
> Hi All
>
> Does anybody have any ideas what I am doing wrong with this code.
>
> What I am trying to do is read data from a Domino Database. For
> purposes of the test I have wrapped the DominoCom object in a C# class
> that runs in a seperate thread.
>
> If I run this code:
> rd = new ReadData(src, 1, 10, this);
> list.Add(rd);
>
> t = new Thread(new ThreadStart(rd.Read));
> t.Name = "Thread " + ++ThreadId;
> t.Start();
>
> rd = new ReadData(src, 30, 20, this);
> list.Add(rd);
> t = new Thread(new ThreadStart(rd.Read));
> t.Name = "Thread " + ++ThreadId;
> t.Start();
>
> rd = new ReadData(src, 100, 30, this);
> list.Add(rd);
>
> t = new Thread(new ThreadStart(rd.Read));
> t.Name = "Thread " + ++ThreadId;
> t.Start();
>
> Which starts three threads it all works as I would expect
>
> but if I do it in a loop (which is what I want to do) the code stops
> at the
> point where it calls into the Domino COM Class.
>
> list = new ArrayList(10);
>
> while (!isComplete)
> {
> if (list.Count < 10)
> {
> rd = new ReadData(src, offset * 10 + 1, docCount, this);
> list.Add(rd);
>
> t = new Thread(new ThreadStart(rd.Read));
> t.Name = "Thread " + ++ThreadId;
> t.Start();
>
> offset++;
> rd = null;
> t = null;
> }
> }
>
> What I dont understand is why this should be any different to starting
> each thread as per the previous example...
>
> If anybody has any ideas I would be grateful...
>
> Regards
>
> Paul Bowman


Hi Nicholas

Thanks for your reply and the info - that was really helpful and
certainly gives me food for thought.

I seem to have corrected the problem by changing the [STAThread] to
[MTAThread] in code. I am not sure if this is the complete answer and
I will research the points you raised.

Once again thanks for your response.

Regards

Paul Bowman

Nov 15 '05 #4

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

Similar topics

31
by: AlexeiOst | last post by:
Everywhere in documentation there are recommendations to use threads from thread pooling for relatively short tasks. As I understand, fetching a page or multiple pages (sometimes up to 50 but not...
7
by: Morris | last post by:
I want to abort a running thread, so I call MyThread.abort() function. My problem is this thread runs "almost" like a while(true) loop and I don't want the Abort() function interrupts the thread at...
2
by: Rahul Anand | last post by:
I have a problem in my multithreaded application. The problem is reproducible very rarely, only once in 6000 similar execution (through same code path). Problem: One of multiple threads gets...
5
by: Chris Botha | last post by:
I am creating a worker thread from inside an aspx page and the thread does the stuff it should do, no problem. However, I have noticed running it in the debugger that it seems as if the threads...
20
by: Frank Rizzo | last post by:
I have a class that handles events from another class. Unfortunately these events arrive on a different thread. How can I marshal the code execution to the thread on which the caller class was...
2
by: Christopher Carnahan | last post by:
I need to figure out how to terminate a thread while it is blocked trying to create a COM object via interop. In a worker thread, I do something like this: Type t = null; Object...
3
by: daan | last post by:
Hello, I have a problem and I can't get the solution for it :( I have a com dll, which i imported as a reference. The com object is part of a class which is multithreaded and will create...
4
by: Mufasa | last post by:
Is there any way to force a thread to abort and really have it abort? I have a thread that every once in a while gets hung to so I kill it. Problem is I have a thread that every once in a while...
5
by: andrew | last post by:
Hi, I have the following issue with the Thread.Abort(): The main thread creates a worker thread which waits on a process termination. void ThreadProc() { Process proc =...
6
by: mehdi | last post by:
Hi folks, You know, the Thread class has got a method named Abort which according to the msdn: "Raises a ThreadAbortException in the thread on which it is invoked, to begin the process of...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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...
0
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...

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.