2011-06-08 66 views
5

请帮我这个,我一直在使用AsyncCtpLibrary和C#5 ctp编译器编写控制台应用程序。我第一次真正运行一个代码等待,我得到了这个:C#5 AsyncCtp BadImageFormatException

System.BadImageFormatException was unhandled 
    Message=An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B) 
    Source=AsyncCtpLibrary 
    StackTrace: 
    Server stack trace: 
     at [...].<Execute>d__1c.MoveNext() 
     at [...].Execute() 
     at [...].<Move>d__1d.MoveNext() in[..]:line 266 
    Exception rethrown at [0]: 
     at System.Runtime.CompilerServices.AsyncVoidMethodBuilder.<SetException>b__1(Object state) 
     at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
     at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 
     at System.Threading.ThreadPoolWorkQueue.Dispatch() 
     at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() 
    InnerException: 

我是否缺少一个dll被引用?

重要的新东西
我失败的方法是这样的:

public async override Task<bool> Execute() 
{ 
    //do stuff 
    await stuff; 
    //do other stuff 
    await base.Execute() 
    //do other stuff 
    return true; 
} 

我已经按照乔恩斯基特的意见试图通过小重现错误少了,现在我可以告诉大家,AWAIT基地.Execute()行是杀手锏!如果我将该行注释掉,则所有内容都会运行,如果我将其保留,则调用我的方法立即失败(不在达到base.Execute()时)。所以我假设ctp编译器做了一些奇怪的事情。为什么?我永远不应该做什么?错误有多大?

旧的东西:

编辑:
至于32位/ 64位的问题,我的系统是32位(在虚拟机内,请注意),而据我所知AsyncCtpLibrary.dll不包含非托管代码。我所有的项目(类库和单一控制台应用程序)都有这样的构建标签:screenshot
什么可能仍然是错误的?


编辑: 我还检查融合日志查看器,所述AsyncCtpLibrary被加载而没有任何错误:

*** Assembly Binder Log Entry (6/10/2011 @ 9:04:11 PM) ***  
The operation was successful.  
Bind result: hr = 0x0. The operation completed successfully.  
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll  
Running under executable C:\Users\Daver\Documents\Visual Studio 2010\Projects\[...]\bin\Debug\MyApp.exe 

--- A detailed error log follows. 

=== Pre-bind state information ===  
LOG: User = WIN-N74LV38NLV3\Daver  
LOG: DisplayName = AsyncCtpLibrary, Version=1.0.4107.18181, Culture=neutral, PublicKeyToken=31bf3856ad364e35  
(Fully-specified)  
LOG: Appbase = file:///C:/Users/Daver/Documents/Visual Studio 2010/Projects/[...]/bin/Debug/ 

LOG: Initial PrivatePath = NULL  
LOG: Dynamic Base = NULL  
LOG: Cache Base = NULL  
LOG: AppName = MyApp.exe  
Calling assembly : MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null. 
=== 

LOG: This bind starts in default load context.  
LOG: Using application configuration file: C:\Users\Daver\Documents\Visual Studio 2010\Projects\[...]\bin\Debug\MyApp.exe.Config  
LOG: Using host configuration file:  
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.  
LOG: Post-policy reference: AsyncCtpLibrary, Version=1.0.4107.18181, Culture=neutral, PublicKeyToken=31bf3856ad364e35  
LOG: GAC Lookup was unsuccessful.  
LOG: Attempting download of new URL file:///C:/Users/Daver/Documents/Visual Studio 2010/Projects/[...]/bin/Debug/AsyncCtpLibrary.DLL.  
LOG: Assembly download was successful. Attempting setup of file: C:\Users\Daver\Documents\Visual Studio 2010\Projects\[...]\bin\Debug\AsyncCtpLibrary.dll  
LOG: Entering run-from-source setup phase.  
LOG: Assembly Name is: AsyncCtpLibrary, Version=1.0.4107.18181, Culture=neutral, PublicKeyToken=31bf3856ad364e35  
LOG: Binding succeeds. Returns assembly from C:\Users\Daver\Documents\Visual Studio 2010\Projects\[...]\bin\Debug\AsyncCtpLibrary.dll.  
LOG: Assembly is loaded in default load context. 

我还检查<Execute>d__1c编译器生成的IL代码类'MoveNext()方法,并且它引用的唯一程序集([assemblyName])是mscorlib,System.Core和AsyncCtpLibrary。


我检查了我的DLL和AsyncCtpLibrary两者的清单,雷说.corflags 0x00000003 // ILONLY 32BITREQUIRED,AsyncCtpLibrary说.corflags 0x00000009 // ILONLY,我不确定这是否可以成为问题。

请帮忙,我出于主意!

回答

6

编辑:我从编译器团队听到回,他们已经证实这是一个错误。它已经在他们的代码库中得到了修复,所以希望我们能够在下一个版本/ beta/CTP中看到这个问题。该修补程序不会被移植到“正常的”VS2010,因为这是一个非常不寻常的情况,至少在异步之前。


编辑:好吧,我现在有一个非常简短但完整的程序,它演示了这个问题。我相信这是仿制药调用基方法的混合物:

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

编辑:好的,我想出了一个解决办法。基本上,要非虚拟地调用基类方法,编译器会在BoolAction中创建一个合成方法。它得到的是稍有不妥,但我们可以得到它的权利:

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

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

所以每当你写base.Execute,写BaseExecute并插入额外的方法。这也不是糟糕的解决方法,直到团队修复错误。

编辑:我简化了这个例子 - 你不需要任何覆盖,特别是你不需要基类来暴露Task<T>。到调用任何虚拟base.Foo方法做到这一点:

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

编辑:相反,我以前的想法,这影响迭代器为好。无需异步CTP ...

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

编辑:它会影响匿名函数太...

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

我可以构建并运行异步样本... – TDaver 2011-06-11 08:34:43

+0

我失败的方法是公共异步覆盖任务执行(),它执行的东西(sequentally),然后有时要求用户输入(从控制台),然后返回true或false。处理这个问题? – TDaver 2011-06-11 08:37:16

+0

@TDaver:我不希望如此,但是,如果你可以尽可能地减少它,直到你有一个最小的失败例子,那真的会有帮助。 – 2011-06-11 09:03:10

0

当您尝试在64位环境中加载32位DLL时,经常会发生此异常。

如果您在64位操作系统上运行,请尝试将您的项目设置更改为直接针对x86(而不是AnyCPU)进行编译。

(这听起来倒退,但是那是因为如果要加载需要强制整个项目以32位外部32位DLL)

+0

我已经将每个项目的属性中的所有项目都设置为x86。没有改变。 :( – TDaver 2011-06-08 21:34:40

+0

也我不认为我正在运行一个64位环境 – TDaver 2011-06-08 22:34:27

+0

我甚至尝试将目标框架设置为完整.net4,仍然没有帮助 – TDaver 2011-06-09 05:40:43

相关问题