2011-06-08 88 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

相關問題