2010-12-16 2 views
0

Pourquoi le code suivant génère-t-il l'erreur suivante?La méthode anonyme génère une exception d'exécution lors de l'accès à la variable locale

private static void CreateNewAppDomain() { 
    var cd = AppDomain.CreateDomain("CustomDomain1"); 
    cd.DomainUnload += (sender, args) => Console.WriteLine("Domain 0 unloading,  sender{0}, args{1} domain {2}", sender, args,cd); 
} 



System.Runtime.Serialization.SerializationException was unhandled Message=Type 'CoreConstructs.AppDomainPlay+<>c__DisplayClass3' in assembly 'CoreConstructs, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2642f93804f4bbd8' is not marked as serializable. Source=mscorlib 
    StackTrace: 
     at System.AppDomain.add_ProcessExit(EventHandler value) 
     at CoreConstructs.AppDomainPlay.CreateNewAppDomain() in C:\work\sampleCode\exploreCsharp\exploreCSharp\ParameterPassing\AppDomainPlay.cs:line 31 
     at CoreConstructs.AppDomainPlay.ExploreAppDomain() in C:\work\sampleCode\exploreCsharp\exploreCSharp\ParameterPassing\AppDomainPlay.cs:line 19 
     at CoreConstructs.Program.Main(String[] args) in C:\work\sampleCode\exploreCsharp\exploreCSharp\ParameterPassing\Program.cs:line 14 
     at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
     at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
     at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     at System.Threading.ThreadHelper.ThreadStart() 
    InnerException: 

Répondre

0

C'est parce que vous essayez d'utiliser la variable cd dans la méthode DomainUnload et cette variable est définie dans le champ extérieur.

+0

Normalement, ce serait bien, non? Le problème ici est-il réellement que l'objet détenu par 'cd' vit dans un AppDomain différent du code exécuté par le gestionnaire OnUnload? Cela expliquerait 'SerializationException'. – Eric

+0

@Eric, oui, c'est le problème ici. –

3

Le compilateur C# génère une classe d'assistance invisible pour implémenter le lambda. Vous pouvez voir son nom dans le message d'exception, <>c__DisplayClass3. Puisque le lambda s'exécute dans le domaine d'application ajouté, l'instance de cette classe d'assistance doit être sérialisée du domaine principal vers ce domaine d'application.

Cela ne fonctionne pas, ces classes auxiliaires n'ont pas l'attribut [Serializable]. Vous ne pouvez pas utiliser un lambda ici, utilisez simplement la syntaxe d'assignation d'événement régulière sur une fonction d'aide statique. Comme ceci:

 cd.DomainUnload += NewAppDomain_DomainUnload; 
    ... 

    private static void NewAppDomain_DomainUnload(object sender, EventArgs e) { 
     Console.WriteLine("AppDomain {0} unloading", AppDomain.CurrentDomain); 
    } 
Questions connexes