WinForms读取FTDI数据时避免UI冻结的Task实现方案
WinForms读取FTDI数据时UI冻结问题排查
开发WinForms GUI应用,通过USB从FTDI芯片读取数据,读取过程中出现UI冻结:窗口失去响应,按钮、最小化/最大化/关闭等窗口控制功能均失效,但Visual Studio调试窗口可见数据正在正常接收。
数据读取基于FTDI驱动的事件机制:ftHandle.SetEventNotification(FTDI.FT_EVENTS.FT_EVENT_RXCHAR, receivedDataEvent);。理论上数据接收逻辑应放在独立线程中执行以避免阻塞GUI,尝试用Task处理线程但仍出现冻结问题,具体代码如下:
初始实现代码
FTDI初始化后启动接收任务
var receivedDataEvent = new AutoResetEvent(false); ftHandle.SetEventNotification(FTDI.FT_EVENTS.FT_EVENT_RXCHAR, receivedDataEvent); // 创建数据接收任务 Task dataReceiveTask = new Task(async () => { while (true) { // 等待FT_EVENT_RXCHAR事件触发 receivedDataEvent.WaitOne(); await Task.Run(() => { ReadDataAvailableInFtdiBuffer(); }); } }); // 启动任务 dataReceiveTask.Start();
数据读取方法
void ReadDataAvailableInFtdiBuffer() { ftStatus = ftHandle.GetRxBytesAvailable(ref numBytesAvailable); if (numBytesAvailable < 1) return; System.Diagnostics.Debug.WriteLine(ftStatus + " bytes available: " + numBytesAvailable.ToString()); byte[] bytes = new byte[numBytesAvailable]; UInt32 numBytesRead = 0; ftHandle.Read(bytes, numBytesAvailable, ref numBytesRead); // -------------------------------------------------------------------------------------------- // 触发数据接收事件,将数据传递给订阅者(USB) // OnFtdiBytesReceived?.Invoke(this, new FtdiBytesReceivedEventArgs(bytes, numBytesAvailable)); // -------------------------------------------------------------------------------------------- }
第一次修改(仍未解决UI冻结)
按照建议改用Task.Run直接创建任务,但UI依旧无响应:
var receivedDataEvent = new AutoResetEvent(false); ftHandle.SetEventNotification(FTDI.FT_EVENTS.FT_EVENT_RXCHAR, receivedDataEvent); // 创建数据接收任务 Task dataReceiveTask = Task.Run(() => { while (true) { // 等待FT_EVENT_RXCHAR事件触发 receivedDataEvent.WaitOne(); ReadDataAvailableInFtdiBuffer(); } });
补充:SetEventNotification函数说明
SetEventNotification函数说明
用于设置当指定FTDI事件发生时,触发一个Windows事件对象。
- 参数1:需要监听的事件(此处为
FT_EVENT_RXCHAR,代表接收缓冲区有数据可读取)- 参数2:指向要触发的Windows事件对象的指针(此处为
AutoResetEvent实例)
当指定事件发生时,FTDI驱动会将该事件对象置为有信号状态。
内容的提问来源于stack exchange,提问作者bLAZ
相关产品推荐
相关产品推荐

