У меня есть проект, над которым я работаю, в котором есть Windows gui (необязательно) и рабочий, который может либо записывать в gui, либо в консоль, если не указано gui. gui не является обязательным, чтобы сделать этот проект обратно совместимым с системами, которые могут не иметь среды рабочего стола (я также могу в конечном итоге переделать этот проект в конечном итоге в C или C ++, но из-за временных ограничений мне нужно что-то, чтобы работать прямо сейчас) , Большинство компьютеров, на которых программа будет работать (пока), имеют Windows XP. (Я нацеливаюсь на NET Framework 4.0.3).
Из-за того, что я хочу, чтобы gui был необязательным, я не хочу, чтобы рабочий класс жил внутри BackgroundWorker
или Form
. В моем реальном проекте у меня есть UserInterface
«интерфейс» (c# интерфейс), который может быть реализован различными пользовательскими интерфейсами.
В Windows GUI tfhere является основным Form
с кнопкой, которая открывает диалог Form
. Диалог имеет многострочное текстовое поле, к которому рабочий может добавлять строки.
Поскольку я не использую BackgroundWorker
или другие общепринятые способы ведения дел, я столкнулся с различными проблемами, связанными с операциями кросс-потоков и вызовом BeginInvoke
до создания дескриптора окна. Мне удалось «решить» проблему дескриптора окна, по сути, вызвав _ = MainForm.Handle
в конструкторе MainForm
, чтобы принудительно создать создание дескриптора окна до того, как будет показано окно (чтобы рабочий мог добавлять строки в текстовое поле, что может произойти до того, как будет показан gui.
Вот мой минимальный, воспроизводимый пример, который отражает проблему, с которой я сталкиваюсь в моем реальном проекте. Проблема возникает, когда либо а) удаляется создание дескриптора окна из конструктора MainForm
, что заставляет BeginInvoke
жаловаться на вызов до создания дескриптора окна, либо б) как есть, когда диалоговое окно закрыл и повторно открыл вызов на ShowDialog
не удается из-за операций с несколькими потоками.
Program.cs
using System;
using System.Windows.Forms;
namespace MinimalExample
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Gui gui = new Gui();
Worker worker = new Worker(gui);
worker.start();
gui.show();
}
}
}
Gui .cs
using System.Windows.Forms;
namespace MinimalExample
{
class Gui
{
private readonly DialogForm _dialog_form;
private readonly MainForm _main_form;
public Gui()
{
_dialog_form = new DialogForm();
_main_form = new MainForm(_dialog_form);
}
public void addLine(string line)
{
_dialog_form.addLine(line);
}
public void show()
{
Application.Run(_main_form);
}
}
}
MainForm.cs
using System;
using System.Windows.Forms;
namespace MinimalExample
{
public partial class MainForm : Form
{
private readonly DialogForm _dialog_form;
public MainForm(DialogForm form)
{
_dialog_form = form;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
_dialog_form.ShowDialog(this);
}
}
}
DialogForm.cs
using System;
using System.Windows.Forms;
namespace MinimalExample
{
public partial class DialogForm : Form
{
public DialogForm()
{
InitializeComponent();
_ = Handle;
_ = textBox1.Handle;
/* Visible = true;
Visible = false; */
}
public void addLine(string line)
{
Action action = () =>
{
textBox1.AppendText(line);
textBox1.AppendText(Environment.NewLine);
};
if (InvokeRequired)
textBox1.BeginInvoke(action);
else
action();
}
}
}
Рабочий .cs
using System;
using System.Threading;
namespace MinimalExample
{
internal class Worker
{
private readonly Gui _gui;
private readonly Thread _thread;
internal Worker(Gui gui)
{
_gui = gui;
_thread = new Thread(new ThreadStart(working));
_thread.IsBackground = true;
}
private void working()
{
while (true)
{
if (_gui != null)
_gui.addLine("Test");
else
Console.WriteLine("Test");
Thread.Sleep(1000);
}
}
public void start()
{
_thread.Start();
}
}
}
Что здесь происходит? И есть ли способ, которым я могу хранить Gui
и Worker
отдельно, но не иметь этих исключений времени выполнения?