在现代应用程序中,响应式用户界面是用户体验的重要组成部分。本文将展示如何在WinForm应用程序中使用异步编程,以便在查找和标识仪器资源时保持界面响应。我们将利用NI-VISA库来实现这一目标,并介绍相关的代码实现和技术细节。
代码实现
以下是一个完整的示例代码,该代码在按下按钮后查找GPIB、TCPIP、ASRL和USB连接的仪器,并将它们的标识信息添加到组合框中。
private async void uiButton12_Click(object sender, EventArgs e)
{
uiPanel5.Visible = true;
uiLabel32.Visible = true;
await Task.Delay(1000); // 异步等待,避免界面冻结
ClearComboBoxes();
await PopulateComboBoxesAsync("GPIB?*", "INSTR");
await PopulateComboBoxesAsync("TCPIP?*INSTR*", "INSTR");
await PopulateComboBoxesAsync("ASRL?*INSTR*", "INSTR");
await PopulateComboBoxesAsync("USB?*", "INSTR");
uiLabel32.Visible = false;
}
private async Task PopulateComboBoxesAsync(string searchPattern, string suffix)
{
var rm = new Ivi.Visa.Interop.ResourceManager();
var ioobj = new Ivi.Visa.Interop.FormattedIO488();
try
{
IEnumerable<string> resourceNames = await Task.Run(() => rm.FindRsrc(searchPattern));
foreach (string resourceName in resourceNames)
{
if (suffix == null || resourceName.Contains(suffix))
{
try
{
ioobj.IO = (Ivi.Visa.Interop.IMessage)rm.Open(resourceName, Ivi.Visa.Interop.AccessMode.NO_LOCK, 0, "");
ioobj.WriteString("*IDN?");
string res0 = await Task.Run(() => ioobj.ReadString());
AddDeviceToComboBoxes(res0, resourceName);
}
catch (Exception ex)
{
MessageBox.Show($"Error communicating with device {resourceName}: {ex.Message}", "Device Communication Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
catch (Exception ex)
{
MessageBox.Show($"Error finding resources with pattern {searchPattern}: {ex.Message}", "Resource Search Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void AddDeviceToComboBoxes(string deviceName, string resourceName)
{
this.Invoke(new Action(() => {
comboBox.Items.Add($"{deviceName} ({resourceName})");
}));
}
private void ClearComboBoxes()
{
comboBox.Items.Clear();
}
代码解析
主事件处理函数 uiButton12_Click
这是用户点击按钮后执行的主要逻辑。
-
显示进度指示:
uiPanel5.Visible = true; uiLabel32.Visible = true;
-
异步等待:
await Task.Delay(1000); // 异步等待,避免界面冻结
-
清空组合框:
ClearComboBoxes();
-
查找和标识仪器: 使用不同的查找模式异步填充组合框。
await PopulateComboBoxesAsync("GPIB?*", "INSTR"); await PopulateComboBoxesAsync("TCPIP?*INSTR*", "INSTR"); await PopulateComboBoxesAsync("ASRL?*INSTR*", "INSTR"); await PopulateComboBoxesAsync("USB?*", "INSTR");
-
隐藏进度指示:
uiLabel32.Visible = false;
填充组合框的异步函数 PopulateComboBoxesAsync
此函数负责查找符合指定模式的资源,并获取其标识信息。
-
创建资源管理器和IO对象:
var rm = new Ivi.Visa.Interop.ResourceManager(); var ioobj = new Ivi.Visa.Interop.FormattedIO488();
-
查找资源: 异步查找资源,避免阻塞UI线程。
Enumerable<string> resourceNames = await Task.Run(() => rm.FindRsrc(searchPattern));
-
处理每个资源:
- 打开资源
- 发送标识查询命令
- 读取响应并添加到组合框
ioobj.IO = (Ivi.Visa.Interop.IMessage)rm.Open(resourceName, Ivi.Visa.Interop.AccessMode.NO_LOCK, 0, ""); ioobj.WriteString("*IDN?"); string res0 = await Task.Run(() => ioobj.ReadString()); AddDeviceToComboBoxes(res0, resourceName);
-
异常处理: 捕获并显示错误信息,保证程序稳定性。
catch (Exception ex) { MessageBox.Show($"Error communicating with device {resourceName}: {ex.Message}", "Device Communication Error", MessageBoxButtons.OK, MessageBoxIcon.Error); }
添加设备到组合框的函数 AddDeviceToComboBoxes
this.Invoke(new Action(() => {
comboBox.Items.Add($"{deviceName} ({resourceName})");
}));
清空组合框的函数 ClearComboBoxes
简单地清空组合框的所有项。
comboBox.Items.Clear();
结论
通过上述代码示例,我们展示了如何在WinForm应用程序中使用异步编程来查找和标识仪器资源。异步编程不仅可以保持用户界面的响应性,还能提升用户体验。如果你在实际应用中遇到类似需求,希望这篇文章能对你有所帮助。