delphi - 用户 GUI Activity 如何破坏我的串行端口输入

标签 delphi user-interface android-activity serial-port corrupt-data

我正在使用来自“大牌”之一的第 3 方串行端口组件(是的,我已要求他们提供支持,但存在时区差异,我需要快速解决此问题)。该组件已经存在多年,我没有理由相信问题出在它身上(硬件软件也是如此)。

硬件规范规定,如果我将某个字符串写入串行端口,以回车符终止,然后读取,它将回复一个特定格式的 8 个字符的字符串,再次以回车符终止。

代码可以运行几个小时,正确执行此操作并根据其读取的内容更新 GUI。

但是,当 GUI 上有任何用户 Activity 时,我会从串行端口读取垃圾内容。

我第一次注意到它是在单击导致模式表单打开然后关闭表单的按钮时。

但是,当我简单地拖动 TStringGrid 的滚动条时,我也会看到它。

这是代码。有什么建议吗?

<小时/>

更新:该组件是线程化的,并且供应商同意此处的海报 - 串行端口是异步设备。我更改了代码以编写数据请求并处理组件的 OnCharReceived() 事件处理程序中收到的每个字符。感谢塔恩斯克的所有帮助。

<小时/>
function TForm1.ReadChannelValueFromSerialPort(
                       device_number : String; channel_number : String) : Real;
   const SLEEP_TIME = 50;         // ms
         NUM_READ_ATTEMPTS = 10;

   var serialPortInput : String;
       read_attempt_counter : Integer;
       messageString : String;
begin
   WriteToSerialPort('#' +  device_number + channel_number + #13);

   serialPortInput := '';
   read_attempt_counter := 0;

   while Length(serialPortInput) = 0 do
   begin
      try
         Application.ProcessMessages();
         serialPortInput := serialPortInput + SerialPort.ReadText();

      except
         on E: Exception do
         begin
            messageString := 'Can''t read from serial port' ;
            MessageDlg(messageString, mtError, [mbOK], 0);
            Halt(0);
         end;
      end;

      Inc(read_attempt_counter);

      if (read_attempt_counter = NUM_READ_ATTEMPTS) 
      and (Length(serialPortInput) = 0) then
      begin
         messageString := 'Can''t read from serial port after trying ' +
                     IntToStr(NUM_READ_ATTEMPTS) + ' times in ' +
           FloatToStr((SLEEP_TIME * NUM_READ_ATTEMPTS) / 1000) + ' seconds';
         MessageDlg(messageString, mtError, [mbOK], 0);
         Halt(0);
      end;

      if (Length(serialPortInput) = 0) then
        Sleep(SLEEP_TIME);
   end;

   if Copy(serialPortInput, 1, 1) <> '>' then
   begin
      DebugBreak();
      MessageDlg('Invalid value read from serial port "' + 
                  serialPortInput + '"', mtError, [mbOK], 0);
      Halt(0);
   end;

    // drop the3 leading >
   serialPortInput := Copy(serialPortInput, 2, Length(serialPortInput) - 1);
   serialPortInput := TrimRight(serialPortInput);  // just in case
   Result := StrToFloat(serialPortInput);
end;  // ReadChannelValueFromSerialPort();

最佳答案

如果不知道您实际使用的是哪个组件,或者它的内部功能,则很难说。但是用户 Activity 会通过主消息队列,并且您的代码正在手动抽取新消息的队列,因此这可能与您的问题有关。您允许在写入和读取之间处理用户 Activity 。您是否尝试过将串行端口逻辑移至单独的工作线程中?

关于delphi - 用户 GUI Activity 如何破坏我的串行端口输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7493402/

相关文章:

德尔福回调?

delphi - 在ADOQuery中更改当前记录之前会触发哪个事件,以及如何不更改当前记录?

delphi - 将 VirtualStringTree 导出到 excel、csv?

android - 如何在不阻塞 Activity 的情况下在 AsyncTask 中创建 while(true)?

android - 方向更改后 fragment 中的 getActivity() 为空

delphi - 如何在 Windows 中 Hook 全局快捷方式?

perl - 我应该为 Perl GUI 使用 Perl/Tk、Tcl::Tk 还是 Tkx?

允许用户移动字段的 Java gui

java - Intellij Java : Jni error has occured

android - 如何在 Android 上将对象从一个 Activity 传递到另一个 Activity ?