public RuntimeModuleHandle Execute(RuntimeExecutionContext context) { RuntimeModuleHandle handle = new RuntimeModuleHandle { ExecutionContext = context }; Task task = new Task(() => ExecuteThreaded(context)); lock (tasks) { tasks.Add(handle, task); } task.Start(); return handle; }
public void ExecuteThreaded(RuntimeExecutionContext context) { var petriNet = context.PetriNetModule.PetriNet; Dictionary<string, Assembly> assemblyCache = new Dictionary<string, Assembly>(); Dictionary<Type, object> objectCache = new Dictionary<Type, object>(); bool suitableActionFound; do { suitableActionFound = false; var transitionsToFire = petriNet.Elements .Where(element => element is ITokenConsumer && ((ITokenConsumer)element).Input .All(input => input.Marking > 0)); foreach (var transition in transitionsToFire) { // Consuming tokens from the input places. if (transition is ITokenConsumer) { (transition as ITokenConsumer).Input.ForEach(input => input.Marking--); } // Executing the methods, if the transition is bound to a method. if (transition is IMethodReference) { var methodReference = (IMethodReference)transition; // Loading type from assembly. Type type; if (!string.IsNullOrEmpty(methodReference.AssemblyFileName)) { Assembly assembly; if (!assemblyCache.TryGetValue(methodReference.AssemblyFileName, out assembly)) { string fileName = Path.IsPathRooted(methodReference.AssemblyFileName) ? methodReference.AssemblyFileName : Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), methodReference.AssemblyFileName); assembly = Assembly.LoadFile(fileName); assemblyCache.Add(methodReference.AssemblyFileName, assembly); } type = assembly.GetType(methodReference.TypeName); } else { type = Assembly.GetEntryAssembly().GetType(methodReference.TypeName); } if (type != null) { // Looking for the appropriate method in the type. MethodInfo methodInfo = type.GetMethod(methodReference.MethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (methodInfo != null) { // Creating a target object (or pulling it from cache) and invoking the method on it. object targetObject; if (!objectCache.TryGetValue(type, out targetObject)) { targetObject = Activator.CreateInstance(type); objectCache.Add(type, targetObject); } methodInfo.Invoke(targetObject, null); suitableActionFound = true; } } } // Placing tokens to the output places. if (transition is ITokenDispatcher) { (transition as ITokenDispatcher).Output.ForEach(output => output.Marking++); } } } while (suitableActionFound); objectCache.Clear(); assemblyCache.Clear(); }