我有一台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的性能比实际的要快得多。或者至少其中带有数据的标签应立即出现和消失。
答案 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);
}
}
该应用程序是一个“婚礼护照”阅读器,可在屏幕上显示姓名,客房编号,表号以及“护照”图片。