5

これを手伝ってください。私はAsyncCtpLibraryとC#5ctpコンパイラを使用してコンソールアプリケーションを作成しています。待っているコードを実際に実行するようになったとき、私はこれを手に入れました:

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

Jon Skeetのアドバイスに従って、間違いを少しずつ再現しようとしましたが、今ではawait base.Execute()行がキラーであることがわかります。その行をコメントアウトすると、すべてが実行されます。そのままにしておくと、メソッドの呼び出しはすぐに失敗します(base.Execute()に到達したときではありません)。だから私はctpコンパイラが何かおかしなことをしていると思います。なんで?私は絶対に何をすべきではありませんか?バグの大きさはどれくらいですか?

古いもの:

編集:
32ビット/ 64ビットの問題に関しては、私のシステムは32ビット(仮想マシン内、気をつけてください)であり、私が知る限り、AsyncCtpLibrary.dllにはアンマネージコードが含まれていません。私のすべてのプロジェクト(クラスライブラリと単一のコンソールアプリ)には、すべて次のようなスクリーンショット
ビルドタブがあります。


編集:Fusionログビューアも確認しました。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.

また、コンパイラで生成されたクラスのMoveNext()メソッドのILコードを確認しました。この<Execute>d__1cメソッドが参照するアセンブリ([assemblyName])は、mscorlib、System.Core、およびAsyncCtpLibraryのみです。


私は自分のdllとAsyncCtpLibraryの両方のマニフェストをチェックしました、私の言いました.corflags 0x00000003 // ILONLY 32BITREQUIRED、AsyncCtpLibraryは言いました.corflags 0x00000009 // ILONLY、これが問題になる可能性があるかどうかはわかりません。

助けてください、私はアイデアがありません!

4

3 に答える 3

6

編集:バグとして確認したコンパイラチームからの返信があります。それはすでに彼らのコードベースで修正されていたので、うまくいけば、次のリリース/ベータ/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();
    }
}
于 2011-06-11T08:21:52.000 に答える
4

既知のVS2010のバグに遭遇しています

https://connect.microsoft.com/VisualStudio/feedback/details/626550/badimageformatexception-on-simple-program-using-generics-and-lambdas

于 2011-06-14T15:01:47.433 に答える
0

この例外は、64ビット環境で32ビットDLLをロードしようとしたときによく発生します。

64ビットOSで実行している場合は、プロジェクト設定を変更して、(AnyCPUではなく)x86用に直接コンパイルしてみてください。

(これは逆に聞こえるかもしれませんが、外部の32ビットDLLをロードする場合は、プロジェクト全体を強制的に32ビットにする必要があるためです。)

于 2011-06-08T20:08:36.857 に答える