2011-06-08 10 views
5

Por favor, ayúdenme con esta, he estado escribiendo una aplicación de consola usando AsyncCtpLibrary y el compilador C# 5 ctp. La primera vez que llegué a ejecutar realmente un código que le espera, tengo esto: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: 

me estoy perdiendo un archivo DLL que se hace referencia?

importantes cosas nuevas
Mi método no se ve así:

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

He seguido los consejos de Jon Skeet tratando de recrear el error poco a poco, y ahora puedo decir que la base Await .Execute() ¡la línea es el asesino! Si comento esa línea, todo se ejecuta, si lo dejo, llamar a mi método falla INMEDIATAMENTE (no al llegar a la base. Ejecutar()). Así que supongo que el compilador ctp hace algo raro. ¿Por qué? ¿Qué nunca debería hacer? ¿Qué tan grande es el error?

cosas viejas:

EDIT:
que para la emisión de 32 bits/64 bits, mi sistema es de 32 bits (en una máquina virtual, que conste), y por lo que yo sé no lo hace AsyncCtpLibrary.dll contiene código no administrado. Todos mis proyectos (bibliotecas de clase y aplicación de consola única) tienen pestañas de compilación como esta: screenshot
¿Qué puede ser todavía incorrecto?


EDIT: I también comprobó el Fusión registro espectador, el AsyncCtpLibrary se carga sin ningún error:

*** 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. 

también he comprobado el código IL del generado por el compilador <Execute>d__1c class 'MoveNext() método, y los únicos ensamblajes a los que hace referencia ([assemblyName]) son mscorlib, System.Core y AsyncCtpLibrary.


he comprobado la manifiesta tanto de mi DLL y AsyncCtpLibrary, la mía dijo .corflags 0x00000003 // ILONLY 32BITREQUIRED, AsyncCtpLibrary dijo .corflags 0x00000009 // ILONLY, no estoy seguro si esto puede ser el problema.

Por favor ayuda, estoy fuera de las ideas!

Respuesta

6

EDIT: He recibido noticias de que el equipo compilador , que lo han confirmado como un error. Ya se había corregido en su código base, así que con suerte veremos esa solución en la próxima versión/beta/CTP.La solución no será retransferida a VS2010 "normal" ya que es un conjunto bastante inusual de circunstancias, al menos antes de la sincronización.


EDIT: Bueno, ahora tengo un programa muy corto pero completo que demuestra el problema. Creo que es una mezcla de los genéricos y llamar a un método de base:

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: Bueno, yo he llegado con una solución. Básicamente, para llamar al método de clase base de forma no virtual, el compilador crea un método sintético en BoolAction. Que se pone un poco mal, pero que puede hacerlo bien:

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

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

Así que cuando estuviera escribiendo base.Execute, escribir BaseExecute e insertar ese método adicional. No es demasiado mal una solución, hasta que el equipo corrige el error.

EDITAR: He simplificado un poco el ejemplo; no necesita ninguna anulación, y en particular no necesita la clase base para exponer un Task<T>. Una llamada a cualquier virtuales base.Foo método lo hará:

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: En contra de mis pensamientos anteriores, este qué efecto iteradores también. No se requiere CTP asíncrono ...

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: Y afecta a funciones anónimas también ...

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

Puedo compilar y ejecutar las muestras asíncronas ... – TDaver

+0

Mi método fallido es como anulación pública asíncrona Tarea Ejecutar(), que hace cosas (secuencialmente), a veces solicita la entrada del usuario (desde la consola) y luego devuelve un verdadero o falso. ¿Es posible que la anulación lo tenga? que tiene que ver con esto? – TDaver

+0

@TDaver: No me lo esperaba, no ... pero si puedes tratar de reducirlo tanto como sea posible, hasta que tengas un mínimo ejemplo de fallas, eso realmente ayudaría. –

0

Esta excepción a menudo se produce cuando intenta cargar un archivo DLL de 32 bits en un entorno de 64 bits.

Si está ejecutando un sistema operativo de 64 bits, intente cambiar la configuración de sus proyectos para compilar directamente para x86 (en lugar de AnyCPU).

(. Esto puede sonar hacia atrás, pero es porque si está cargando una externa DLL de 32 bits que necesita para obligar a todo el proyecto a ser de 32 bits)

+0

tengo establezco todos mis proyectos Build Target en x86 en las propiedades de cada proyecto. Nada ha cambiado. :( – TDaver

+0

también no creo que esté ejecutando un entorno de 64 bits – TDaver

+0

Incluso he intentado establecer el marco de destino en .net4 completo, todavía no ayudó – TDaver