Пример #1
0
        /// <summary>
        /// Start multiple sessions in one run continuously.
        /// </summary>
        /// <param name="subject">subject name</param>
        /// <param name="sessionDescriptors">descriptors of each session</param>
        /// <param name="paradigms">paradigms of each session</param>
        /// <param name="devices">devices used across sessions</param>
        /// <param name="sessionListener"></param>
        public static void StartSessions(string subject, [NotNull] string[] sessionDescriptors, [NotNull] SerializedObject[] paradigms, [CanBeNull] DeviceConfig[] devices,
                                         ISessionListener sessionListener = null)
        {
            subject = subject?.Trim2Null() ?? throw new UserException("subject name cannot be empty");
            if (sessionDescriptors == null)
            {
                throw new ArgumentNullException(nameof(sessionDescriptors));
            }
            if (paradigms == null)
            {
                throw new ArgumentNullException(nameof(paradigms));
            }
            if (sessionDescriptors.Length != paradigms.Length)
            {
                throw new ProgrammingException("The count of session descriptors and the count of paradigms are not equal");
            }
            for (var i = 0; i < sessionDescriptors.Length; i++)
            {
                sessionDescriptors[i] = sessionDescriptors[i]?.Trim2Null() ?? throw new UserException("session descriptor name cannot be empty");
            }
            var sessionNum = sessionDescriptors.Length;

            /* Constructs paradigm instances. */
            var paradigmInstances           = new IParadigm[sessionNum];
            var formattedSessionDescriptors = new string[sessionNum];

            for (var i = 0; i < sessionNum; i++)
            {
                var paradigm = paradigms[i];
                if (!App.Instance.Registries.Registry <ParadigmTemplate>().LookUp(paradigm.Id, out var paradigmTemplate))
                {
                    throw new ArgumentException($"Cannot find specific paradigm by id: {paradigm.Id}");
                }
                var paradigmContext = paradigmTemplate.DeserializeArgs(paradigm.Args);
                if (!TryInitiateParadigm(paradigmTemplate, paradigmContext, out var paradigmInstance))
                {
                    return;
                }
                paradigmInstances[i]           = paradigmInstance;
                formattedSessionDescriptors[i] = SessionConfigExt.StringInterpolation(sessionDescriptors[i], paradigmContext);
            }

            var deviceTypeMap = App.Instance.Registries.Registry <DeviceTypeAddOn>().Registered.Select(pdt => pdt.DeviceType).ToDictionary(dt => dt.Name);

            /* Constructs device map and consumers map. */
            var deviceMap           = new Dictionary <DeviceType, DeviceConfig>();
            var deviceConsumerLists = new Dictionary <DeviceType, IList <TemplateWithArgs <ConsumerTemplate> > >();

            if (devices != null)
            {
                foreach (var deviceConf in devices)
                {
                    if (deviceTypeMap.TryGetValue(deviceConf.DeviceType, out var deviceType) && !deviceMap.ContainsKey(deviceType))
                    {
                        deviceMap[deviceType] = deviceConf;
                        var list = new List <TemplateWithArgs <ConsumerTemplate> >();
                        deviceConsumerLists[deviceType] = list;
                        if (deviceConf.Consumers == null)
                        {
                            continue;
                        }
                        foreach (var consumerConf in deviceConf.Consumers)
                        {
                            if (consumerConf.Id == null)
                            {
                                continue;
                            }
                            if (!App.Instance.Registries.Registry <ConsumerTemplate>().LookUp(consumerConf.Id, out var consumerTemplate))
                            {
                                throw new ArgumentException($"Cannot find specific consumer by id: {consumerConf.Id}");
                            }
                            list.Add(new TemplateWithArgs <ConsumerTemplate>(consumerTemplate, consumerTemplate.DeserializeArgs(consumerConf.Args)));
                        }
                    }
                }
            }

            /* IMPORTANT: ALL PARADIGM RELATED CONFIG SHOULD BE CHECKED BEFORE STEAMERS WERE INITIALIZED */
            var deviceInstances = InitiateDevices(deviceTypeMap.Values, deviceMap);

            var sessions  = new Session[sessionNum];
            var baseClock = Clock.SystemMillisClock;
            var streamers = CreateStreamerCollection(deviceTypeMap.Values, deviceInstances, baseClock, out var deviceStreamers);

            sessionListener?.BeforeAllSessionsStart();

            var disposablePool = new DisposablePool();

            try
            {
                streamers.Start();

                for (var i = 0; i < sessionNum; i++)
                {
                    var session = sessions[i] = new Session(App.Instance.Dispatcher, subject, formattedSessionDescriptors[i],
                                                            baseClock, paradigmInstances[i], streamers, App.DataDir);

                    new SessionConfig {
                        Subject = subject, SessionDescriptor = sessionDescriptors[i], Paradigm = paradigms[i], Devices = devices
                    }
                    .JsonSerializeToFile(session.GetDataFileName(SessionConfig.FileSuffix), JsonUtils.PrettyFormat, Encoding.UTF8);

                    foreach (var entry in deviceConsumerLists)
                    {
                        if (deviceStreamers.TryGetValue(entry.Key, out var deviceStreamer))
                        {
                            var  consumerListOfDevice = entry.Value;
                            var  indexed = consumerListOfDevice.Count > 1;
                            byte num     = 1;

                            foreach (var consumerWithParams in consumerListOfDevice)
                            {
                                System.Diagnostics.Debug.Assert(consumerWithParams.Template != null, "consumerWithParams.Template != null");
                                var consumer = consumerWithParams.Template.NewInstance(session, consumerWithParams.Args, indexed ? num++ : (byte?)null);
                                disposablePool.AddIfDisposable(consumer);
                                deviceStreamer.AttachConsumer(consumer);
                                disposablePool.Add(new DelegatedDisposable(() => deviceStreamer.DetachConsumer(consumer)));
                            }
                        }
                    }

                    sessionListener?.BeforeSessionStart(i, session);
                    var result = session.Run();
                    sessionListener?.AfterSessionCompleted(i, session);

                    disposablePool.DisposeAll(); // Release resources.

                    new SessionInfo(session).JsonSerializeToFile(session.GetDataFileName(SessionInfo.FileSuffix), JsonUtils.PrettyFormat, Encoding.UTF8);
                    result?.Save(session);

                    if (session.UserInterrupted && i < sessionNum - 1 &&
                        MessageBox.Show("Continue following sessions?", "User Exit", MessageBoxButton.YesNo,
                                        MessageBoxImage.Question, MessageBoxResult.No, MessageBoxOptions.None) == MessageBoxResult.No)
                    {
                        break;
                    }
                }
            }
            finally
            {
                disposablePool.Dispose();
                streamers.Stop();
            }
            foreach (var instance in deviceInstances.Values)
            {
                instance.Dispose();
            }
            sessionListener?.AfterAllSessionsCompleted(sessions);
        }