Обновление пользовательского интерфейса из обработчика событий NFC-Tag-Reader выполняется очень медленно - PullRequest
0 голосов
/ 19 января 2019

У меня есть считыватель ACR122U NFC, где я читаю метки MiFare UltraLight NFC. Я скачал рамки для моего читателя. Однако когда вызывается обработчик событий, обновление графического интерфейса происходит очень медленно.

У меня мало опыта в многопоточном программировании и обработке событий. Может быть, решение моего вопроса очень просто.

Однако он обновляет только «метка за меткой» в методе UpdateInterface () и один за другим. Я вижу, как исчезает каждый ярлык. Таким образом, обновление пользовательского интерфейса происходит очень медленно.

Полагаю, это как-то связано с (аппаратными) событиями, вызываемыми классами читателей в фоновом режиме.

Программа обычно работает только очень медленно.

private void StartMonitor()
{
        //Function called when starting the Windows Forms Application
        IMonitorFactory monitorfactory = MonitorFactory.Instance;
        monitor = monitorfactory.Create(SCardScope.System);
        monitor.Start(ReaderNames[0]);
        monitor.StatusChanged += Monitor_StatusChanged;
}

private void Monitor_StatusChanged(object sender, StatusChangeEventArgs e)
{
        strPassportNo = "";
        strPassportNo = lPassportNumberNo.Text;

        if (e.NewState.ToString().ToLower().Contains("empty".ToLower()) == true)
        {
            //Interface should be deleted all by once now as no NFC tag is on the reader.
            UpdateInterface();
        }
}

private void UpdateInterface()
{
        if (InvokeRequired)
        {
            this.BeginInvoke(new Action(() =>
            {
                lPassportNumberNo.Text = "";
                lPassengerName.Text = "";
                lPax.Text = "";
                lTableNo.Text = "";
                lRoomNo.Text = "";
                pbTables.Hide();
                pbPasspic.Hide();
                this.BackgroundImage = BackgroundWelcome;
            }));
        }
        else
        {
            lPassportNumberNo.Text = "";
            lPassengerName.Text = "";
            lPax.Text = "";
            lTableNo.Text = "";
            lRoomNo.Text = "";
            pbTables.Hide();
            pbPasspic.Hide();
            this.BackgroundImage = BackgroundWelcome;
        }
}

Ожидаемый результат должен заключаться в том, что производительность пользовательского интерфейса намного выше, чем на самом деле. Или, по крайней мере, ярлыки с данными должны появляться и исчезать сразу.

Ответы [ 2 ]

0 голосов
/ 19 января 2019

Обновление пользовательского интерфейса было в моем случае, чтобы просто очистить метки (см. UpdateInterface ()). Однако я обнаружил «ошибку». Это был файл ".jpg" и BackgroundImage, который я загружал при каждом обновлении. Хотя это было «просто» 1280x1024, это было слишком много для обновления интерфейса.

Когда я очистил Изображения, обновление было немедленно.

Мое решение сейчас:

this.BackgroundImage = ((System.Drawing.Image(resources.GetObject("$this.BackgroundImage")));
this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.SetStyle(System.Windows.Forms.ControlStyles.OptimizedDoubleBuffer | System.Windows.Forms.ControlStyles.AllPaintingInWmPaint, true);

в Form1.Designer.cs

и Приостановка и возобновление макета со следующим классом (который я нашел где-то в Интернете)

public static class ControlHelper
{
    #region Redraw Suspend/Resume
    [DllImport("user32.dll", EntryPoint = "SendMessageA", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
    private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
    private const int WM_SETREDRAW = 0xB;

    public static void SuspendDrawing(this Control target)
    {
        SendMessage(target.Handle, WM_SETREDRAW, 0, 0);
    }

    public static void ResumeDrawing(this Control target) { ResumeDrawing(target, true); }
    public static void ResumeDrawing(this Control target, bool redraw)
    {
        SendMessage(target.Handle, WM_SETREDRAW, 1, 0);

        if (redraw)
        {
            target.Refresh();
        }
    }
    #endregion
}

Также я изменил файлы ".jpg" на файлы ".bmp". Теперь интерфейс работает плавно и быстро.

И @Jesting:

Не уверен, что это на самом деле: this.BackgroundImage = BackgroundWelcome; но действительно ли необходимо каждый раз назначать такие статические данные?

Нет, я мог бы найти лучшее решение. Однако, поскольку приложение очень маленькое, и у меня есть только четыре фоновых изображения, мне было проще «жестко закодировать» его.

Наконец, тег (-reader) на самом деле не был проблемой.

И для обновления пользовательского интерфейса я использую эту довольно простую функцию:

private void UpdateInterface(PassportDatabaseReader.Passport _passport)
    {
        if (InvokeRequired)
        {
            this.BeginInvoke(new Action<PassportDatabaseReader.Passport>(UpdateInterface), new object[] { _passport });
            return;
        }
        else
        {
            ControlHelper.SuspendDrawing(this);
            new Thread(() => ChangeBackground(BackgroundPassport)).Start();
            lPassportNumberNo.Text = _passport.PassportNo;
            strPassportNo = _passport.PassportNo;
            lPassengerName.Text = _passport.Name.Replace('$','\n');
            lPax.Text = _passport.Pax;
            lTableNo.Text = _passport.TableNo;
            lRoomNo.Text = _passport.RoomNo;
            pbTables.Hide();
            try
            {
                pbPasspic.Load("..\\..\\Pics\\" + _passport.PassportNo + ".png");
                pbPasspic.Show();
                pbTables.ImageLocation = "..\\..\\Tischordnung_" + _passport.TableNo + ".png";
                pbTables.Show();
            }
            catch (Exception)
            {
                throw;
            }
            ControlHelper.ResumeDrawing(this);
        }
    }

Приложение представляет собой считыватель "свадебного паспорта", который отображает на экране имя, номер комнаты для гостей, номер стола, а также изображение "паспорта".

0 голосов
/ 19 января 2019

Не уверен, что это на самом деле: this.BackgroundImage = BackgroundWelcome; но действительно ли необходимо каждый раз назначать такие статические данные?

Кроме того, я не думаю, что частота вашего события обновления слишком высока - информация на экране должна быть удобочитаемой, так что это определенно только одно обновление всех данных, необходимых после прочтения всего тега. Если для каждого тега имеется много событий чтения - сохраните их во временный список и обновите форму в конце чтения (весь тег). Когда я говорю «метка», я имею в виду все содержимое карты mifare.

...