This Question is Answered

2 "helpful" answers available (2 pts)
4 Replies Last post: Aug 1, 2008 1:51 PM by Vadim Ridosh  
Dan   6 posts since
Jul 28, 2008
Currently Being Moderated

Jul 31, 2008 7:03 AM

Need help invoking COM methods on another thread

 

Hello,

 

 

I'm trying to invoke methods on a COM object that was passed to me by a VB application.  It works fine when methods are called from inside the Java COM server method that this object is passed into, however when I try to use that same object from a JDialog, I get the error  "COM object method returns error code: 0x8001010E; The application called an interface that was marshalled for a different thread."  I know the problem is that the COM object was created on another thread, but I don't know how to get it to work on my Swing thread.  I've tried experimenting with the OleMessageLoop but can't make that work either.

 

 

Here is what is in my Java COM Server class:

 

 

    // configuration is VB COM object

    public void configure(_Configuration configuration) {

        // This succeeds

        System.out.println("Name: " + configuration.getName().getValue());

 

 

        TestDialog dlg = new TestDialog(configuration);

        dlg.setVisible(true);

    }

 

 

 

And this is what I have inside my dialog when a button is pressed:

 

 

    private void btTest_actionPerformed(ActionEvent e) {

        // This fails

        System.out.println("Name: " + configuration.getName().getValue());

    }

 

 

Any ideas?  I'm using the latest 2.4 ComfyJ libraries.

 

 

Thanks,

Dan

 

 

Vadim Ridosh TeamDev Ltd. 74 posts since
Jul 23, 2008
Currently Being Moderated
1. Jul 31, 2008 12:36 PM in response to: Dan
Re: Need help invoking COM methods on another thread

Hi, Dan

 

You should use OleMessageLoop.bindObject for this task - it creates a proxy object that always execute function calls in the scope of right OleMessageLoop. There is a code example:

 


private _Configuration configurationProxy;

// configuration is VB COM object
public void configure(_Configuration configuration) {

configurationProxy = (_Configuration) OleMessageLoop.getInstance().bindObject(configuration);

System.out.println("Name: " + configurationProxy.getName().getValue());

TestDialog dlg = new TestDialog(configurationProxy);
dlg.setVisible(true);
}

private void btTest_actionPerformed(ActionEvent e) {
// This fails
System.out.println("Name: " + configurationProxy.getName().getValue());
}

 

Regards,

Vadim Ridosh

Vadim Ridosh TeamDev Ltd. 74 posts since
Jul 23, 2008
Currently Being Moderated
3. Jul 31, 2008 4:29 PM in response to: Dan
Re: Need help invoking COM methods on another thread

Hi Dan,

 

I think roots of the problem can be in wrong place (thread, actually) where you called bindObject function. Try to call it directly after you obtained _Configuration pointer from VB code. If this won't help, could you please send me more sample code to reproduce the problem?

 

Regards,

Vadim Ridosh

Vadim Ridosh TeamDev Ltd. 74 posts since
Jul 23, 2008
Currently Being Moderated
4. Aug 1, 2008 1:57 PM in response to: Dan
Re: Need help invoking COM methods on another thread

Hi Dan,

 

It seems these pointers are actually marshaled for the thread other then thread where OleMessageLoop works. To workaround this, you should use COM marshaling functions:

 

   // This method receives interfaces from VB code
    public void TestProfile(_DriverProfile driverProfile) {
        try {
            // Create stream to marshal interface
            IStream strm = OleFunctions.coMarshalInterThreadInterfaceInStream(new IUnknownImpl(driverProfile));
            TestDialog dlg = new TestDialog(strm); // Pass this stream to dialog
            dlg.setVisible(true);                                    
        } catch (Throwable th) {
            th.printStackTrace();
            JOptionPane.showMessageDialog(null, th.getMessage());
        }
    }

 

 

public class TestDialog extends javax.swing.JDialog {
    private IStream stream; // Stream is stored in the dialog
 
    /** Creates new form TestDialog */
    public TestDialog(IStream stream) {
        super((javax.swing.JDialog)null, true);
        initComponents();
        this.stream = stream;
    }

 

 

private void btnTestActionPerformed(java.awt.event.ActionEvent evt) {
    ComFunctions.coInitialize(); // Initialize COM
    IUnknownImpl unk = new IUnknownImpl();
    stream.seek(new Int64(0l), new StreamSeek(StreamSeek.STREAM_SEEK_SET)); // Set Stream pointer to the beginning
    OleFunctions.coUnmarshalInterface(stream, new IID(_DriverProfile.INTERFACE_IDENTIFIER), unk); // Unmarshal interface
    _DriverProfile profileProxy = new _DriverProfileImpl(unk); // Call QI
    System.out.println(profileProxy.getDriverName()); // It works now.
}

 

 

In this sample unmarshaling performed each time btnTestActionPerformed called. For performance reasons, this can be performed only once per thread, in this case unmarshaled pointer can be stored permanently (in thread local memory, for example). I did not included this in code to keep it simple.

 

Regards,

Vadim Ridosh

More Like This

  • Retrieving data ...