Solved

Threading problem in COM service

Posted on 2002-07-02
25
522 Views
Last Modified: 2013-12-14
Hi all,
I have COM NT service and two interfaces in it. Lets say someone calls method DoSomething from first interface IOne. This method should wait for some event (e.g. certain value in DB, or something like that) and then return it to the caller. The point is, calls to this and other interfaces should be possible during execution of this method.

So here is my problem: other calls aren't possible until execution of first method isn't over.

I've tried to change interface threading model from Apartment (default) to Free. It doesn't help.

Here's code of DoSomething:

STDMETHODIMP COne::DoSomething(short *iRetVal)
{    
     for(int i=0;i<20;i++)
     {
          Sleep(1000);
     }
     *iRetVal = 555;

     return S_OK;
}

Maybe Sleep() doesn't provide "interrupt" for other processes to be called? I've tried other wait functions (SleepEx, WaitForMultipleObjectEx), it's all the same.

Thanx.
0
Comment
Question by:Rimvis
  • 11
  • 5
  • 4
  • +3
25 Comments
 
LVL 32

Expert Comment

by:jhance
ID: 7124480
The problem is that you are calling Sleep().  This locks the interface until this function returns.

Don't call Sleep() and this won't happen.

If you have long running operations in your COM object and don't want to hang on them, setup connection points that your client application can subscribe to.  Your COM server can then run the long operation in a thread and send a notification when it completes.  But any calls to a COM object should return as quickly as possible if you want to continue using it.
0
 
LVL 19

Author Comment

by:Rimvis
ID: 7124509
As I said, I tried to use SleepEx or WaitForMultipleObjectEx. They worked same as Sleep() to me.
jhance, what do you suggest instead of Sleep()? I need some function to wait for some time until next value check will be launched.

//this loop will check for some value
for(int i=0;i<20;i++)
{
       //value check will be here

       //wait 1 second until next check
       Sleep(1000);
}
//return that value
*iRetVal = 555;

And that's the point, I want to "hang" on that method, until value isn't returned, or some timeout expires. I'm sure it can be done, but I don't know how :o(
0
 
LVL 32

Accepted Solution

by:
jhance earned 50 total points
ID: 7124529
Sleep or WaitFor are equivalent in this context.  You CANNOT stop the thread in a call and expect the interface to continue to offer its services.

Perhaps the Microsoft information about non-blocking method calls at:

http://msdn.microsoft.com/library/en-us/dncomg/html/nbmc.asp

will be helpful for you to review.
0
 
LVL 3

Expert Comment

by:jimbucci
ID: 7126598
The DoSomething() method is not a thread - but a blocking function - yes it will block until it is done because it is a regular function.  Putting any wait state into the function just increases the delay.  If you want to have other functions be callable you need make this function do as little as possible.   It can possibly kick off a thread that does your checking for you and then fires an event when it is done.  

As a personal rule, I have my interface methods do as little as possible.  Any lengthy processes are handled by threads or other class functions.  This gives a quick response time to the object.

So to possibly answer your question, have DoSomething() kick off a thread that does your event checking, then return S_OK if the thread was created successfully or some other error if not.  This thread will then fire a connection point indicating that the event has occurred or some error condition exists - a possible parameter in the callback function.

Also, you must use some wait state (WaitFor....) or Sleep() so that you relinquish the CPU to the system.  Otherwise you will see your system slow to a crawl while your thread uses 99% of the CPU.  

Let me know if this helps or if you need further assistance.
Jim
0
 
LVL 19

Author Comment

by:Rimvis
ID: 7126752
To jhance:

Thanx, I gues non-blocking method calls are axactly what I need. Sadly, I can't make working project out of link you posted.

DO YOU KNOW LINK TO WORKING PROJECT OR HAVE ONE READY BY CHANCE?

Article says single async_uuid(...) is enough for C++ clients. Well, it's not working. When I try to compile project, errors like "error C2065: 'ICallFactory' : undeclared identifier" occures.
To call COM object, I'm importing .tlb file to client and then "using namespace ...;". Is it right in this situation? Worked in other COM projects.

When I try to add Java/VB support in IDL file (in COM server), I get "error MIDL2337 : unsatisfied forward declaration : ICallFactory [ Coclass 'One'  ]"
0
 
LVL 19

Author Comment

by:Rimvis
ID: 7126754
Maybe I did something wrong in IDL file? Here it is:

// AsyncCallA.idl : IDL source for AsyncCallA.dll
//

// This file will be processed by the MIDL tool to
// produce the type library (AsyncCallA.tlb) and marshalling code.

import "oaidl.idl";
import "ocidl.idl";
     [
          object,
          uuid(5FAD1998-0638-48E4-BBE8-2044EB126178),
          async_uuid(CFB610DC-9553-48d2-8A14-938AF4025128),
          helpstring("IOne Interface"),
          pointer_default(unique)
     ]
     interface IOne : IUnknown
     {
          [helpstring("method DoSomething")] HRESULT DoSomething([out, retval] short* iRes);
     };

[
     uuid(39E50045-47D0-4B45-8A2F-73AB8179BF7A),
     version(1.0),
     helpstring("AsyncCallA 1.0 Type Library")
]
library ASYNCCALLALib
{
     importlib("stdole32.tlb");
     importlib("stdole2.tlb");

     [
          uuid(8FBAEEF2-956F-41EB-B35E-34BF22D175A1),
          helpstring("One Class")
     ]
     coclass One
     {
          [default] interface IOne;
          interface ICallFactory;
     };
     [
          uuid(46F0D4B5-C76F-4516-A264-86C089BEE7C7),
     ]
     coclass AsyncOne
     {
          [default] interface AsyncIOne;
          interface ISynchronize;
          interface ICancelMethodCalls;
     };
};
0
 
LVL 19

Author Comment

by:Rimvis
ID: 7126770
To jimbucci:

I want COM object to return resul in same call, whithout events.
Future project will be called from ASP and SOAP. I don't think they support such things as events, or are they? Don't know much about it though :o/
0
 
LVL 32

Expert Comment

by:jhance
ID: 7126809
IMHO, you've just gone off on a HUGE tangent to this question.  You have a generic design flaw in your application and need to re-architect.

Getting the project I referenced to compile is not your problem.  You need to study and understand it and apply the concept there to your application's design.
0
 
LVL 3

Expert Comment

by:jimbucci
ID: 7126865
There are a few ways to do this:
1.  Calling the function that initiates the wait will force you to wait until the action is completed.  ASP may have a problem with this unless you set the timeout in your ASP application.

2.  Create another function that starts a thread that queries the DB, or whatever - and returns - no waiting.
In your ASP code, create a loop or timer that queries your object to see if the event db is ready.  Once ready you do something else - whatever it is that is to be done once the event has occurred.

I have a similar DCOM application that an ASP app connects to and gets status information from.  When the DCOM server is started it initializes its data and gets the information ready for the client so that the client doesn't need to call any init functions.  The client then polls the server.  If there is no info available the server returns a blank string.  

If you need to manually initialize the COM server then let the COM server handle its initialization and let you know when it's done.  

For ASP, you are right about the events - once the ASP is translated it is gone so it cannot handle events.  THe only way is to poll the object.

Also, if ASP is your target client, you will need to make the object IDispatch since scripting languages cannot handle custom objects.  (Correct me if I'm wrong)

I hope this helps.  Let me know if you need additional info.

ps jhance:  I thought you were the nicest expert on EE... :)



0
 
LVL 32

Expert Comment

by:jhance
ID: 7126885
I am, but putting band-aids on a deep architectural problem is like painting over termite infested wood.  It looks OK on the outside, for a while, but the underlying structure is compromised.  It won't stand up over time or under stress.

A poorly architected application or component is the same.  You do nobody any favors by proposing a superficial fix to a deep problem.
0
 
LVL 32

Expert Comment

by:jhance
ID: 7126887
And besides that, what did I say that wasn't nice?
0
 
LVL 19

Author Comment

by:Rimvis
ID: 7126952
OK, maybe I should drop idea of using non-blocking calls in THIS situation. Anyway, I just noticed it doesn't support IDispatch interface.

Gues I will make something like this:
1) method MustDoSomething tells server to begin some action ant returns S_OK immediatly.
2) some inner thread does the job
3) method IsSomethigDone returns job result or some value if it's not done yet.

BUT, idea of non-blocking calls looks interesting.

So, jhance, will you be a nice (:oP) expert and help me with my problem with project compilation? Plz :o)

Thanx.
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 3

Expert Comment

by:jimbucci
ID: 7126955
I don't consider my ideas a band-aid.

Architecturally the COM server needs some fixing so that it doesn't get stuck if the event never occurs.  Using ASP as the client presents lots of limitations not seen with C++.  Waiting for the COM server is not a good option for ASP as it is impatient and will fail with timeout errors.  The app will have to poll the COM server for status.

The IDL file does not look too complex so fixing it will not be a big deal.  Remove the async_uuid() since it won't work with IDispatch, which is required for ASP.

This would require restructuring of the COM server, but I don't see anything major - adding a thread is no big deal.

jhance: Yeah, I suppose you're not unfriendly.

Jim
0
 
LVL 19

Author Comment

by:Rimvis
ID: 7161394

I want my interface to support async calls. And that's where I'm stuck.
I have no problem writing simple interface, that supports IDispatch.

So, can  anybody help me? I could add some points extra ;o)
0
 
LVL 22

Expert Comment

by:ambience
ID: 7164021
seems like there is a file ObjIdl.idl that is shipped with VS.NET installation that contains interface defition for ICallFactory, perhaps you need to update any SDKs etc.

I cant seem to find that file with VC 6.0 installation, mayeb some service pack is required.
0
 
LVL 19

Author Comment

by:Rimvis
ID: 7164084
I've found "ObjIdl.idl" file from VS.NET.
Can I use it in VC6 project? And how? Just by including it in my project?
0
 
LVL 22

Expert Comment

by:ambience
ID: 7164101
I am not sure though, maybe the interfaec isnt registered on the system, maybe you can try it , here is how youinclude it

in your idl file add a line

#import "oac*"
#import "objidl.idl"
0
 
LVL 19

Author Comment

by:Rimvis
ID: 7164111
Thanx, I'll try it. I have .NET SDK installed BTW.
0
 
LVL 19

Author Comment

by:Rimvis
ID: 7249073
To ambience

I've tried to import files you mentioned. It doesn't work

Is this syntax valid? import "oac*"?
However, I have no files named oac*.*

Then I tried this:

...
import "C:\Program Files\Microsoft Visual Studio .NET\Vc7\PlatformSDK\Include\objidl.idl"
...

It gives me compilation error:

C:\Program Files\Microsoft Visual Studio .NET\Vc7\PlatformSDK\Include\objidl.idl(147) : error MIDL2025 : syntax error : expecting a type specification near "SIZE_T"

It looks like importing .NET IDL's to VC6 wasn't a good idea.

0
 
LVL 22

Expert Comment

by:ambience
ID: 7250448
>> Is this syntax valid? import "oac*"?

no its not a valid syntax, my fault, i should've been explicit about that

#import "oac*"

meant only that there must be some imports like oacidl.idl and oac<something>.idl , i still dont remember the exact names thats why i wrote it as oac*.idl

If you have visual studio .NET installed perhaps you can try building your projects using VC7. This would ensure you get the right libs and headers to play with.
0
 
LVL 11

Expert Comment

by:griessh
ID: 7353369
Dear Rimvis

I think you forgot this question. I will ask Community Support to close it unless you finalize it within 7 days. You can always request to keep this question open. But remember, experts can only help you if you provide feedback to their questions.
Unless there is objection or further activity,  I will suggest to split between

     "jhance and jimbucci"

comment(s) as an answer.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
======
Werner
0
 
LVL 19

Author Comment

by:Rimvis
ID: 7355057
griessh:

Well, I haven't forgot this question. I just dont have VC7 (and free time) right now to test proposed answers. And I dont know, when I will :o/

So, I'm totaly agree with you about splitting points.
0
 
LVL 6

Expert Comment

by:Mindphaser
ID: 7419739
Rimvis

You want to reward points to these experts:

I reduced the points to 50 and refunded the rest. Please accept one experts comment as an answer and post a 50p question for the other expert with a title like : "Points for xxx" and a body "For your help in  ."

** Mindphaser - Community Support Moderator **
0
 
LVL 3

Expert Comment

by:jimbucci
ID: 7419960
I forgot about this question too.  I would like to know  your final solution - just for curiosity.

Good luck.
Jim
0
 
LVL 19

Author Comment

by:Rimvis
ID: 7423648
Thanx for all experts, who helped me. I'm accepting jhence answer.

Experts AMBIENCE and JIMBUCCI, please visit C++ section to collect your points.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

With most software applications trying to cater to multiple user needs nowadays, the focus is to make them as configurable as possible. For e.g., when creating Silverlight applications which will connect to WCF services, the service end point usuall…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now