C # Как лучше всего управлять потоками в консольном CLI-приложении с некоторыми элементами WinForm - PullRequest
0 голосов
/ 13 апреля 2019

Я разрабатываю консольное приложение на основе CLI, в котором большая часть тяжелой работы выполняется с помощью апплетов, сценариев и инструкций командной строки.

Некоторые апплеты, однако, используют WinForms, и эта функциональность была добавлена ​​и работает достаточно хорошо, если формы активируются через «Form.ShowDialog ()» (в отличие от просто «Form.Show».() ").

Я предполагаю, что это потому, что созданная форма делится потоком сообщений с базовым (консольно-ориентированным) приложением, и эти два не играют хорошо вместе.

После хеширования мы решили, что не хотим приостанавливать CLI, когда форма открыта (не в последнюю очередь потому, что мы хотим иметь возможность открывать несколько независимых форм), поэтому я предполагаю, что мне нужно создать экземплярновые формы в собственных темах, но эта идея кричит "СЛИШКОМ СЛОЖНО!"мне интересно, есть ли более эффективные / оптимизированные средства для достижения этой цели?

Могу ли я как-то создать отдельный поток, отдельный от базового, в котором все формы могут делиться (как встандартное приложение Windows Forms?) Если да, то как мне реализовать это?

В настоящее время уже запущены и запущены три потока ->

  1. Оригинал (базовый) Консольный поток, который я получаю при первоначальном выполнении EXE-файла.
  2. Поток, который ожидает Console.KeyAvailable и захватывает / управляет всеми нажатиями клавиш и анализом ввода, а также отображением подсказок и созданием вызываемых команд.
  3. Поток, который управляет списком команд и обрабатывает любые новые команды, которые появляются в этом списке (они могут быть добавлены из потока ввода с клавиатуры, или апплетом, или скриптом).

FWIW, "команды" - это просто строки, которые создают экземпляр операции (запускают апплет, получают доступ к встроенной функции и т. Д.).

Когда "exвызывается эта функция, она завершает поток прослушивания клавиатуры, а затем освобождает поток выполнения команды (на котором он выполняется), позволяя ему выйти и вернуть управление обратно операционной системе.

В настоящее время другиечем иногда медлительная отзывчивость в потоке клавиатуры, все работает точно так, как задумано, за исключением, как отмечалось ранее, когда я пытаюсь создать экземпляр WinForm через .Show вместо .ShowDialog

Любые идеи, предложения или указатели будуточень признателен!

Также: я прочитал несколько веток перед публикацией этого сообщения в поисках ответов (то есть это -> , как запустить winform из консольного приложения? ), но они кажутся всемПредположим, что панель консоли будет использоваться как ее собственное назначение (т. е. консоль Windows), а не как кооптированный как независимый интерфейс CLI, поэтому я не нашел ничего, что действительно решало бы этот конкретный сценарий использования, оставляя меня по-прежнемунемного в темноте на данный момент!(и ДЕЙСТВИТЕЛЬНО не желая рассматривать необходимость написания базового механизма управления для создания / закрытия уникальных, независимых потоков для каждой открываемой формы!).

Спасибо!

1 Ответ

0 голосов
/ 15 апреля 2019

Это потому, что Form.ShowDialog () выполняет свой собственный цикл запуска, а Form.Show () - нет.Вы должны выполнить runloop самостоятельно, вызвав Application.Run ().

Однако вы должны установить какую-то связь между потоками.В следующем примере я использовал hiddenForm.BeginInvoke (), который отправляет вызов метода в очередь сообщений приложения.Это единственная причина существования hiddenForm.

Конечно, вы можете использовать Task, Thread или все, что вам подходит вместо BackgroundWorker.

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace ConsoleWithForms
{
    class Program
    {
        static BackgroundWorker worker;
        static MyForm hiddenForm; 

        static void Main(string[] args)
        {
            worker = new BackgroundWorker();
            worker.DoWork += DoWork;
            worker.RunWorkerAsync();

            Console.WriteLine("Type 'form' or 'quit'...");

            for (var quit = false; !quit;)
            {
                var line = Console.ReadLine().ToLower();
                switch (line)
                {
                    case "quit": quit = true; InvokeCommand("quit"); break;
                    case "form": InvokeCommand("form"); break;
                    default: break;
                }
            }
        }

        private static void DoWork(object sender, DoWorkEventArgs e)
        {
            Application.EnableVisualStyles();
            hiddenForm = new MyForm();
            hiddenForm.Show();
            hiddenForm.Hide();
            Application.Run();
        }

        private static void InvokeCommand(string command)
        {
            hiddenForm.BeginInvoke((Action)delegate {
                hiddenForm.PerformCommand(command);
            });
        }
    }

    class MyForm : Form
    {
        public MyForm()
        {
            Text = "MyForm";
            var button = new Button { Text = "New Form", AutoSize = true };
            button.Click += (sender, args) => { new MyForm().Show(); };
            Controls.Add(button);
        }

        public void PerformCommand(string command)
        {
            switch(command)
            {
                case "form": new MyForm().Show(); break;
                case "quit": Application.ExitThread(); break;
                default: break;
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...