Click here to Skip to main content
15,885,278 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I'm developing an application for demonstrating Silverlight 4.0 and OpenCL interop. I'm using Silverlight's AutomationFactory to cooperate with COM inproc-server written in C# 4.
Silverlight app (COM cilent) calls Solve method from COM server, as solving can take some time, it should run in background, for that reason i've prepared COM interface with event for sending results back to silverlight (SL app registers for COM event).
For now everything works fine, call is synchronous, so SL app waits until solving is done, then COM server fires event and successfully sends results to app.

Problem occurs when I try to run solving asynchronously, not to block Silverlight app UI.
Method A: I've been trying asynchronous call only in COM server - solving works fine untill firing event - here I'm getting exception:
C#
System.Reflection.TargetException was caught
  Message=Object does not match target type.
  Source=mscorlib
  StackTrace:
       at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters)
       at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
       at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
       at Server.IProblemEngineEvents.ProblemSolvedEvent(String performanceResults)
       at Server.ProblemEngine.SendResults(IAsyncResult asyncResult) in ProblemEngine.cs:line 468

This exception (Object does not match target type) seems to be wrong, because event works fine on synchronous call (single thread).

Here is my code:

COM events interface: (Server.IProblemEngineEvents)
C#
[Guid(...),
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[ComVisible(true)]
public interface IProblemEngineEvents
{
    [DispId(1)]
    void ProblemSolvedEvent(String performanceResults);
}

COM interface: (Server.IProblemEngine)
C#
[Guid(...)]
[ComVisible(true)]
public interface IProblemEngine
{
    .....
    [DispId(2)]
    void Solve(String problemFileName, String datasetFileName);
}

COM Server: (Server.ProblemEngine)
C#
[Guid(...),
ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(IProblemEngineEvents))]
[ComVisible(true)]
public class ProblemEngine : IProblemEngine
{
    private delegate SolveResults SolveDelegate(String problemFileName, String datasetFileName);
    public event ProblemSolvedDelegate ProblemSolvedEvent;

    [ComVisible(true)]
    // entry point
    public void Solve(String problemFileName, String datasetFileName)
    {
        // asynchronous call
        SolveDelegate solveDlgt = new SolveDelegate(InnerSolve);
        IAsyncResult result = solveDlgt.BeginInvoke(
            problemFileName,
            datasetFileName,
            new AsyncCallback(SendResults),
            solveDlgt);
    }

    // doing some calculations and returns results
    private SolveResults InnerSolve(String problemFileName, String datasetFileName)
    {....}

    // callback method called after solving is finished
    // this callback is still in new thread
    private void SendResults(IAsyncResult asyncResult)
    {
        ...
        if (null != this.ProblemSolvedEvent)
        {
            try
            {
                // HERE comes exception
                // System.Reflection.TargetException was caught
                //  Object does not match target type.
                this.ProblemSolvedEvent(serializedResults);
            }....
         }
    }

Silverlight app (COM Client, SolverManager.InnerSolve), calling code:
C#
public void InnerSolve()
{
    try
    {
        // ProblemEngine is dynamic COM object reference from AutomationFactory
        ProblemEngine.Solve(currentProblemName, currentDatasetFile);
    }...
}


Method B: I've also tried background worker in SL app (COM client) to run whole Solve method from COM in background thread - here the exception is as follows:
C#
System.InvalidOperationException was caught
  Message=Invalid cross-thread access.
  StackTrace:
       at MS.Internal.Error.MarshalXresultAsException(UInt32 hr, COMExceptionBehavior comExceptionBehavior)
       at MS.Internal.ComAutomation.ComAutomationNative.CheckInvokeHResult(UInt32 hr, String memberName, String exceptionSource, String exceptionDescription, String exceptionHelpFile, UInt32 exceptionHelpContext)
       at MS.Internal.ComAutomation.ComAutomationNative.Invoke(Boolean tryInvoke, String memberName, ComAutomationInvokeType invokeType, ComAutomationInteropValue[] rgParams, IntPtr nativePeer, ComAutomationInteropValue& returnValue)
       at MS.Internal.ComAutomation.ComAutomationObject.InvokeImpl(Boolean tryInvoke, String name, ComAutomationInvokeType invokeType, Object& returnValue, Object[] args)
       at MS.Internal.ComAutomation.ComAutomationObject.Invoke(String name, ComAutomationInvokeType invokeType, Object[] args)
       at System.Runtime.InteropServices.Automation.AutomationMetaObjectProvider.TryInvokeMember(InvokeMemberBinder binder, Object[] args, Object& result)
       at System.Runtime.InteropServices.Automation.AutomationMetaObjectProviderBase.<.cctor>b__4(Object obj, InvokeMemberBinder binder, Object[] args)
       at CallSite.Target(Closure , CallSite , Object , String , String )
       at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid3[T0,T1,T2](CallSite site, T0 arg0, T1 arg1, T2 arg2)
       at SolverManager.InnerSolve()

Exception is thrown before geting into COM's Solve method.

Code differences for method b:
COM:
C#
...
public class ProblemEngine : IProblemEngine
{
   ...
    [ComVisible(true)]
    // entry point
    public void Solve(String problemFileName, String datasetFileName)
    {
        InnerSolve();
    }

    // doing some calculations
    // sending results
    private void InnerSolve(String problemFileName, String datasetFileName)
    {
       SendResults(results);
    }

    private void SendResults(string results)
    {
        ...
        if (null != this.ProblemSolvedEvent)
        {
            try
            {
                this.ProblemSolvedEvent(results);
            }....
         }
    }

Silverlight:
C#
public void Init()
{
    bw = new System.ComponentModel.BackgroundWorker();
    bw.WorkerReportsProgress = true;
    bw.WorkerSupportsCancellation = true;
    bw.DoWork += new System.ComponentModel.DoWorkEventHandler(DoWorkCallback);
    bw.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(RunWorkerCompletedCallback);

   bw.RunWorkerAsync();
}

private void DoWorkCallback(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    ...
    InnerSolve();
    ...
}


public void InnerSolve()
{
    try
    {
        // ProblemEngine is dynamic COM object reference from AutomationFactory
        // HERE comes exception: 
        // "System.InvalidOperationException:
        //  Invalid cross-thread access."
        ProblemEngine.Solve(currentProblemName, currentDatasetFile);
    }...
}

Again I have no idea what's wrong. What i found is that it is often caused by updating silverlight UI from another thread, but i'm not doing anything like that.

I've been searching solution for few days and found nothing.
I don't know if problem is caused by some aspects of using COM itself or rather some Silverlight's restrictions with threads.
As i said before, everything works fine when not using asynchronous calls or bw.
(COM is registered during installation.)

Any help will be welcome.
Posted
Comments
Alexxx3001 28-Mar-11 9:50am    
Hi i've the same problem! Did you find a workaroud?

1 solution

I found a solution for this.

Check out this post
You will need to call your event like this.

SynchronizationContext.Current.Post(o => DataReceived(sender, (int) (e.EventType)), null);
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900