Пытаясь понять читатель - PullRequest
0 голосов
/ 02 декабря 2010

Я пытаюсь понять какой-то код.Это небольшая программа, которая распечатывает данные журнала.Это делается путем создания формы с 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 ]

2 голосов
/ 02 декабря 2010

Q1.Почему businessLogic.DoWork работает как поток, а не как обычный вызов метода?

А1.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 голос
/ 02 декабря 2010

1) Похоже, BusinessLogic выполняет долгую работу.Чтобы пользовательский интерфейс реагировал во время этой обработки, он выполняется в другом потоке.

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

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

...