从NFC-Tag-Reader事件处理程序更新UI非常慢

时间:2019-01-19 16:27:54

标签: c# winforms nfc

我有一台ACR122U NFC读取器,可在其中读取MiFare UltraLight NFC标签。我为读者下载了一个框架。但是,在调用事件处理程序时,GUI的更新非常慢。

我在线程编程和事件处理方面经验不足。也许我的问题的解决方案很简单。

但是,它仅更新UpdateInterface()方法中的“逐个标签”,并且一次全部更新。我可以看到每个标签都消失了。因此,UI的更新非常慢。

我想这与后台读者类调用的(硬件)事件有关。

该程序通常只能运行很慢。

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;
        }
}

预期的输出应该是UI的性能比实际的要快得多。或者至少其中带有数据的标签应立即出现和消失。

2 个答案:

答案 0 :(得分:0)

不确定这实际上是什么:this.BackgroundImage = BackgroundWelcome;,但是否真的有必要每次分配这样的静态数据?

我也不认为您的更新事件的发生频率太高-屏幕上的信息应该是人类可读的,因此在读取整个标签后,绝对只是对所有所需数据的一次更新。如果每个标签都有许多读取事件,则将所有事件存储到临时列表中,并在读取端更新整个表单(整个标签)。 当我说“标签”时,是指整个mifare卡内容。

答案 1 :(得分:0)

就我而言,UI更新只是清除标签(请参见UpdateInterface())。但是我发现了“错误”。这是我每次刷新时加载的“ .jpg”文件als 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

并使用以下类(我在Internet上的某个位置)暂停和恢复布局

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;但是真的有必要每次分配这样的静态数据吗?

不,我本可以找到更好的解决方案。但是,由于该应用程序非常小,而且我只有四个背景图像,因此发现对其进行“硬编码”更加容易。

最后,标签(阅读器)并不是真正的问题。

为了更新UI,我使用了这个非常简单的功能:

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);
        }
    }

该应用程序是一个“婚礼护照”阅读器,可在屏幕上显示姓名,客房编号,表号以及“护照”图片。