1

I've created small portable library (reference, targeting: Windows, Windows 8, Windows Phone 7.5) for educational purposes. I've decided to use it in my small Windows 8 Metro style app. Unfortunately, when I call method from the library the exception is thrown:

The application called an interface that was marshalled for a different thread.

at the following line:

return Activator.CreateInstance(outputType, constructorArguments.ToArray());

(Resolve method) The outputType is a typeof(ClassFromMyMetroStyleApp). Library is added to project as dll reference.

What can I do to fix this issue?

Edit: Method is call from UnitTest in Metro Style App solution:

[TestClass]
public class ResolvingTypesTests
{
    /// <summary>
    /// The school context interface test.
    /// </summary>
    [TestMethod]
    public void SchoolContextTest()
    {
        var schoolContext = TypeService.Services.Resolve<ISchoolContext>();

        Assert.AreEqual(typeof(SchoolCollection), schoolContext.GetType());
    }
}

where TypeService is static class, and Services is static property of IResolvable type (interface is provided by Library).

Services property:

/// <summary>
    /// The resolvable.
    /// </summary>
    private static IResolvable resolvable;

    /// <summary>
    /// Gets the type services.
    /// </summary>
    public static IResolvable Services
    {
        get
        {
            if (resolvable == null)
            {
                var builder = new ContainerBuilder();
                builder.Register();
                resolvable = builder.Build();
            }

            return resolvable;
        }
    }
  • Is `ClassFromMyMetroStyleApp` a UI class? And what are `constructorArguments`? – Peter Ritchie May 01 '13 at 13:52
  • 1
    This is a COM marshaling error, heavily used in Store apps. The cause is unclear but very high odds that you'll need to tell your test runner to initialize the thread that runs the test properly. Here is a [sample question](http://stackoverflow.com/questions/2434067/how-to-run-unit-tests-in-stathread-mode) that discusses the same problem. – Hans Passant May 01 '13 at 23:21

3 Answers3

0

You can get this error in a Single-Threaded Apartment when you use certain objects (usually UI objects) in one thread that was created in another thread.

Peter Ritchie
  • 35,463
  • 9
  • 80
  • 98
  • ClassFromMyMetroStyleApp is simple class that implements ISchoolProvider only (and has no base type). constructorArguments is a array of instances of ClassFromMyMetroStyleApp parameters. In this case that array is empty (ClassFromMy.. has parameterless constructor). –  May 01 '13 at 14:16
  • sorry, i meant ISchoolContext, not ISchoolProvider :-) –  May 01 '13 at 14:20
0

Found out the solution (thanks to Hans Passant for clue!) Need to add an attribute to the test method:

[UITestMethod]
-1

No only because of cross thread access but also performance reasons, Activator is discouraged to use. http://bloggingabout.net/blogs/vagif/archive/2010/04/02/don-t-use-activator-createinstance-or-constructorinfo-invoke-use-compiled-lambda-expressions.aspx

Here author has provided a comparison between Activator and using Lambda expression to instantiate the object. I wrapped the code in a single method for u. Try this

public object CreateObject(Type type)
    {

        var ctor = type.GetConstructor(new Type[]{});
        // Make a NewExpression that calls the ctor with the args we just created
        NewExpression newExp = Expression.New(ctor, null);

        // Create a lambda with the New expression as body and our param object[] as arg
        LambdaExpression lambda = Expression.Lambda(newExp, null);

        // Compile it
        var compiled = lambda.Compile();
        if (compiled != null)
        {
        }
        return compiled.DynamicInvoke();
    }
ZafarYousafi
  • 8,640
  • 5
  • 33
  • 39
  • Not really sure how this applies to the question. Your reference doesn't detail how this would avoid a cross-thread exception, plus it applies to compiled expressions--which isn't what the OP is using. – Peter Ritchie May 01 '13 at 14:11
  • downvote? I just proposed an altenative way to instantiate object which is better than activator and does not produce cross thread exceptions – ZafarYousafi May 01 '13 at 14:18
  • i think it's worth a try. I'll check it later (5-6hrs,I'm out of home right now). –  May 01 '13 at 14:24
  • Unfortunately, code is not working - LambdaExpression has no Compile() method. –  May 01 '13 at 20:18
  • I turned out, that Portable Class Library does not support Compile Method. There is no FormatterServices. Need to use CreateInstance and get rid of error. –  May 01 '13 at 21:53
  • Ok, I know what was wrong. In the constructor of ClassFromMyMetroStyleApp I've been creating new BitmapSource instance. It caused thread error. –  May 02 '13 at 07:04
  • Marked as answer - lambda expression method helped me to find the cause. One question - how can I provide instances of construtor parameteres in your wrapped method? –  May 02 '13 at 07:13
  • Need to modify the code a little. I'll update the modified method soon. – ZafarYousafi May 02 '13 at 10:42