调用CreateInstance会导致线程错误

本文关键字:线程 错误 CreateInstance 调用 | 更新日期: 2023-09-27 18:11:52

我创建了一个小型便携式库(参考,目标:Windows, Windows 8, Windows Phone 7.5)用于教育目的。我决定在我的小Windows 8 Metro风格的应用程序中使用它。不幸的是,当我从库调用方法时,抛出异常:

应用程序调用了为另一个线程编组的接口。

:

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

(解决方法)outputType是一个类型的(ClassFromMyMetroStyleApp)。库被添加到项目中作为dll引用。

我能做什么来解决这个问题?

编辑:方法是从Metro Style应用程序解决方案中的UnitTest调用的:

[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());
    }
}

其中TypeService是静态类,Services是IResolvable类型的静态属性(接口由库提供)。

服务属性:

/// <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;
        }
    }

调用CreateInstance会导致线程错误

当你在一个线程中使用在另一个线程中创建的某些对象(通常是UI对象)时,你可以在单线程公寓中得到这个错误。

找到了解决方案(感谢Hans Passant提供的线索!)需要为测试方法添加一个属性:

[UITestMethod]

不鼓励使用Activator,不仅是因为跨线程访问,还因为性能原因。http://bloggingabout.net/blogs/vagif/archive/2010/04/02/don-t-use-activator-createinstance-or-constructorinfo-invoke-use-compiled-lambda-expressions.aspx

这里作者提供了Activator和使用Lambda表达式实例化对象之间的比较。我将代码包装在u的一个方法中。试试

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();
    }