C#5 AsyncCtp BadImageFormatException

匆匆过客 提交于 2019-12-04 07:43:07

EDIT: I've heard back from the compiler team, who have confirmed it as a bug. It had already been fixed in their codebase, so hopefully we'll see that fix in the next release / beta / CTP. The fix isn't going to be back-ported to "normal" VS2010 as it's a pretty unusual set of circumstances, at least before async.


EDIT: Okay, I've now got a really short but complete program which demonstrates the problem. I believe it's a mixture of generics and calling a base method:

using System;
using System.Threading.Tasks;

public abstract class AsyncAction<T>
{
    public virtual Task<T> Execute()
    {
        // We never get this far
        Console.WriteLine("Execute called");
        return null;
    }
}

public class BoolAction : AsyncAction<bool>
{
    public async override Task<bool> Execute()
    {
        return await base.Execute();
    }
}

class Test
{
    static void Main()
    {
        BoolAction b = new BoolAction();
        b.Execute();
    }
}

EDIT: Okay, I've come up with a workaround. Basically, to call the base class method non-virtually, the compiler creates a synthetic method in BoolAction. It gets that slightly wrong, but we can get it right:

public class BoolAction : AsyncAction<bool>
{
    public async override Task<bool> Execute()
    {
        return await BaseExecute();
    }

    private Task<bool> BaseExecute()
    {
        return base.Execute();
    }
}

So whenever you were writing base.Execute, write BaseExecute and insert that extra method. It's not too bad a workaround, until the team fix the bug.

EDIT: I've simplified the example a bit - you don't need any overrides, and in particular you don't need the base class to expose a Task<T>. A call to any virtual base.Foo method will do it:

public abstract class AsyncAction<T>
{
    public virtual T GetT()
    {
        return default(T);
    }
}

public class BoolAction : AsyncAction<bool>
{
#pragma warning disable 1998 // We're not awaiting anything
    public async void Execute()
    {
        base.GetT();
    }
#pragma warning restore 1998
}

class Test
{
    static void Main()
    {
        BoolAction b = new BoolAction();
        b.Execute();
    }
}

EDIT: Contrary to my previous thoughts, this does affect iterators as well. No async CTP required...

public abstract class Base<T>
{
    public virtual T GetT()
    {
        return default(T);
    }
}

public class Derived : Base<bool>
{
    public System.Collections.IEnumerator Foo()
    {
        base.GetT();
        yield break;
    }
}

class Test
{
    static void Main()
    {
        Derived d = new Derived();
        d.Foo().MoveNext();
    }
}

EDIT: And it affects anonymous functions too...

using System;

public abstract class Base<T>
{
    public virtual T GetT()
    {
        return default(T);
    }
}

public class Derived : Base<bool>
{
    public void Foo()
    {
        Action x = () => base.GetT();
        x();
    }
}

class Test
{
    static void Main()
    {
        Derived d = new Derived();
        d.Foo();
    }
}

This exception often occurs when you try and load a 32 bit DLL in a 64 bit environment.

If you are running on a 64 bit OS try changing your projects settings to compile directly for x86 (rather than AnyCPU).

(This might sound backwards, but it's because if you are loading an external 32 bit DLL you need to force your whole project to be 32 bit.)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!