Пытаясь понять читатель

Я пытаюсь понять какой-то код. Это небольшая программа, которая печатает данные журнала. Это делается путем создания формы с DataGridView, которая заполняется DataTable. Класс формы также имеет функцию обновления (RefreshPresentation). Класс BusinessLogic выполняет актуальную работу по обновлению DataTable и вызову функции обновления в форме. Так что я довольно хорошо понимаю функциональность, но не то, почему программа структурирована так, как она есть.

  1. Почему businessLogic.DoWork выполняется как поток, а не как обычный вызов метода?
  2. Может кто-нибудь объяснить мне функцию RefreshPresentation? (BeginInvoke и делегат)
  3. Это хорошая идея / практика, чтобы передать 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 класс для уведомления об изменении данных.

Другие вопросы по тегам