/// <summary> /// Creates, configures and runs a new thread of type PipeDaemon, which will be responsible of /// listening on the pipe dedicated to the communication with the one-shot process that sends /// (when the user requests it) to start a file transfer. /// </summary> private void InitPipeDaemonThread() { /* Create, configure and start the thread responsible of managing the communication on a pipe * with the application which inform this process of the path of the file the user wants to send. */ pipeListener = new PipeDaemon(); /* Register on the pipeListener a callback to execute when the user wants to send * a new file. */ pipeListener.popHappened += (List <string> paths) => { // On the gui thread Application.Current.Dispatcher.Invoke((Action) delegate { /* Create a new SelectionWindow and register a callback to execute when * the user has selected the list of receivers. */ SelectionWindow sw = new SelectionWindow(paths); openedWindow.Add(sw); sw.Selected += (List <Peer> selected, List <string> filepaths) => { // Close the window sw.Close(); /* For each peer in the list schedule a new job on a job scheuler. */ JobScheduler scheduler = new JobScheduler(); // Register a callback to execute in case of connection errors scheduler.ConnectionError += (Job j) => { if (j.Status == Job.JobStatus.ConnectionError) { bf.NotifyError(BackgroundForm.ErrorNotificationType.Sending, BackgroundForm.ErrorDirection.Sending); } }; scheduler.FileError += manageIOException; for (int i = 0; i < selected.Count; i++) { ExecutableThread worker = scheduler.scheduleJob(new SendingJob(new FileTransfer.Task(Settings.Instance.LocalPeer.Id, Settings.Instance.LocalPeer.Name, selected.ElementAt(i).Id, selected.ElementAt(i).Name, filepaths), filepaths)); outgoingJobThreads.Add(worker); } }; sw.Show(); sw.Activate(); }); }; // Run the thread which will listen on the pipe pipeListener.run(); }
/// <summary> /// This method is necessary to make the parent aware of the existence of /// a new thread created in its execution flow. If a child is registered /// to this parent it will enter in the execution cycle managed by this class. /// We must register a specific callback on Terminate event: if this child /// dies we will hinerit all of its childs. In this way, even if a parent /// dies, all of its childs will be passed to its parent ExecutableThread /// so that the hierarchy will not be lost. /// </summary> /// <param name="child"></param> public void RegisterChild(ExecutableThread child) { // we must register a child to childs.Add(child); // NOTE: We must not remove the child from the list in the // following Terminate callback: if we do this, we will not find // the child in the childs list anymore. // We register a callback on terminating: we must pass receive // all the childs of the registered child if he will die. child.Terminate += () => { foreach (ExecutableThread c in child.Childs) { childs.Add(c); } }; }