Oggi stavo eseguendo il debug di un mio codice che creava alcuni ExpressionTrees, li compila per chiamare i Delegati e li chiama in seguito, se necessario. Nel fare questo ho incontrato un FatalExecutionEngineError
passo attraverso il codice:C# Expressions - FatalExecutionEngineError
All'inizio ero un po 'scioccata dal momento non avevo idea di quello che avrebbe potuto eventualmente sbagliato con le mie espressioni, sembravano tutti bene. Poi ho scoperto che questo avviene solo nella seguente situazione:
Method A
è un metodo statico che viene chiamato e genera l'ExpressionTree, che può eventualmente contenere unExpression.Call()
aMethod A
nuovamente. Quindi, dopo aver compilato il Lambda per ExpressionTree, il delegato generato (chiamiamoloMethod B
) potrebbe causare la ricorsione se lo chiamo all'interno di questo metodo ... (Method A
->[Generated]Method B
->Method A
).... che è totalmente possibile nel mio scenario. Come descritto sopra stavo eseguendo il debug di questo pezzo di codice, quindi ho impostato un punto di interruzione in
Method A
.La prima volta che
Method A
viene chiamato dal codice normale, il punto di interruzione viene colpito come al solito. Quando viene chiamato il numeroMethod B
, il punto di interruzione viene eseguito una seconda volta, tutto è ancora in ordine.Ma non appena lascio la seconda chiamata con il debugger scavalcando l'ultima riga, il
FatalExecutionEngineError
verifica.
Se faccio funzionare il codice senza debug, o non si sale nella chiamata ricorsiva a Method A
, O se non passo oltre l'ultima riga del metodo, il problema non si verifica e il mio codice espressione è eseguito come previsto.
Non riesco a determinare se si tratta di un errore nel VS-Debugger o in .NET Framework, o se faccio qualcosa di orribilmente, orribilmente sbagliato che si presenta solo durante il debug delle righe pertinenti.
Ecco un codice di esempio molto semplice che è possibile eseguire senza problemi. Sto usando Visual Studio 2013 Prof Update 4 e .NET 4.5.1. Basta impostare un punto di interruzione nel DoSomething()
e provare a passare alla fine - se possibile;)
Qualcuno può confermare un errore o la mia espressione è mal formata?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ExpressionProblem
{
public class MainClass
{
public static void DoSomething(bool stop)
{
var method = typeof(MainClass).GetMethod(
"DoSomething",
BindingFlags.Public | BindingFlags.Static,
Type.DefaultBinder,
new Type[] { typeof(bool) },
null);
var expParam = Expression.Parameter(typeof(bool), "stop");
var expCall = Expression.Call(null, method, expParam);
var lambda = Expression.Lambda(expCall, expParam);
var @delegate = lambda.Compile();
if(!stop)
{
@delegate.DynamicInvoke(true);
}
}
public static void Main(string[] args)
{
DoSomething(false);
}
}
}
Wow! Funziona/esplode! :-) – xanatos
Ottengo la stessa cosa quando si utilizza VS2012 o VS2010, ma solo quando si utilizzano i passaggi descritti. Scoppia solo se passo in '@ delegate.DynamicInvoke', quindi continuo a scavalcare (non lasciandolo girare). – Shlomo
Poiché funziona correttamente quando non esegue il debug, suppongo che sia un problema con il debugger. – Shlomo