Пытаясь понять читатель
Я пытаюсь понять какой-то код. Это небольшая программа, которая печатает данные журнала. Это делается путем создания формы с DataGridView, которая заполняется DataTable. Класс формы также имеет функцию обновления (RefreshPresentation). Класс BusinessLogic выполняет актуальную работу по обновлению DataTable и вызову функции обновления в форме. Так что я довольно хорошо понимаю функциональность, но не то, почему программа структурирована так, как она есть.
- Почему businessLogic.DoWork выполняется как поток, а не как обычный вызов метода?
- Может кто-нибудь объяснить мне функцию RefreshPresentation? (BeginInvoke и делегат)
- Это хорошая идея / практика, чтобы передать MainForm в качестве параметра в BusinessLogic?
Это основная точка входа для приложения.
public class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
Это соответствующая часть формы.
public partial class MainForm : Form
{
private BusinessLogic businessLogic;
private DataTable viewDataTable;
public MainForm()
{
InitializeComponent();
businessLogic = new BusinessLogic(this);
Thread t = new Thread(new ThreadStart(businessLogic.DoWork));
t.Start();
}
public delegate void RefreshPresentationDelegate(DataTable dataTable);
public void RefreshPresentation(DataTable dataTable)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new RefreshPresentationDelegate(RefreshPresentation), new object[] { dataTable });
return;
}
...
Это бизнес-логика.
internal class BusinessLogic
{
private MainForm form;
private Logging.DAL.Logger loggerDAL;
private int lastId;
internal DataTable DataTable { get; private set; }
internal bool IsRunning { get; set; }
public BusinessLogic(MainForm form)
{
this.form = form;
this.loggerDAL = new Logging.DAL.Logger();
this.IsRunning = true;
DataTable = new DataTable();
}
public void DoWork()
{
while (this.IsRunning)
{
// Get new log messages.
if (DataTable.Rows.Count > 0)
this.lastId = (int)DataTable.Rows[DataTable.Rows.Count - 1]["Id"];
this.DataTable = loggerDAL.GetLogMessagesSinceLastQuery(lastId);
// Callback to GUI for update.
form.RefreshPresentation(this.DataTable);
// Wait for next refresh.
Thread.Sleep(1000);
}
}
}
2 ответа
Q1.Почему businessLogic.DoWork выполняется как поток вместо обычного вызова метода?
A1. DoWork должен быть в отдельном потоке, чем основной поток GUI, так как основной поток GUI должен быть свободен для прокачки очереди сообщений (что позволяет ему перерисовывать себя, обрабатывать различные события GUI и т. Д.) Попробуйте создать простую программу GUI это имеет некоторое время (true) в главном потоке и видит, что графический интерфейс застревает и не перерисовывается.
Q2. Может кто-нибудь объяснить мне функцию RefreshPresentation? (BeginInvoke и делегат)
A2. Хотя DoWork должен выполняться в другом потоке, чтобы он не блокировал поток GUI, обновление GUI всегда должно выполняться из потока GUI. Чтобы это произошло, вы можете вызвать BeginInvoke, который отправляет сообщение в очередь сообщений и вызывает выполнение вашего делегата в потоке GUI.
Q3. Является ли хорошей идеей / практикой передавать MainForm в качестве параметра в BusinessLogic?
A3. Нет. MainForm может знать о бизнес-логике, но бизнес-логика не должна знать о GUI. Google "MVC" для получения дополнительной информации об отделении GUI от бизнес-логики.
1) выглядит как BusinessLogic
делает долгую работу. Чтобы пользовательский интерфейс реагировал во время этой обработки, он выполняется в другом потоке.
2) RefreshPresentation()
является методом, отвечающим за обновление / обновление пользовательского интерфейса во время фоновой обработки, чтобы поддерживать актуальность пользовательского интерфейса. Поскольку пользовательский интерфейс не может быть изменен из потока, кроме самого потока пользовательского интерфейса, необходимо использовать Invoke()
/BeginInvoke()
методы для отправки этого кода в поток пользовательского интерфейса.
3) Я лично считаю, что это плохая идея, и вместо этого событие должно быть разоблачено BusinessLogic
класс для уведомления об изменении данных.