我刚刚在 C# 中创建了一个应用程序,它使用一个线程轮询 UART 以获取接收事件。 如果收到数据,则会在我的主线程 (GUI) 中触发一个事件,并通过 PerformStep() 方法控制进度条(当然,我之前设置了 Max 值因此)。 PerformStep 使用以下表达式调用以处理跨线程
this.Invoke((Action)delegate{progressBar2.PerformStep();})
运行此应用程序时,进度条永远不会达到其最终值。它停在 80%。当调试并停在上述行时,使用单个步骤一切正常。我不知道发生了什么!
在主线程上启动读线程:
pThreadWrite = new Thread(new ThreadStart(ReadThread));
pThreadWrite.Start();
阅读主题:
private void ReadThread()
{
while(1)
{
if (ReceiveEvent)
{
FlashProgressBar();
}
}
}
在主线程中触发的事件:
private void FlashProgressBar()
{
this.Invoke((Action)delegate { progressBar2.PerformStep();});
}
(这是我的代码的简化表示)
似乎内部进度比视觉进度更快。
编辑 2: 好的,我想我明白了。问题在于处理跨线程的调用 方法。我在 SO 上找到了这句话:
不,至少就 Windows 而言,它是任何 UI 的基础。 Windows 窗体中的消息体系结构并不是什么新鲜事物,它甚至与 C++ 应用程序在 Windows 中的工作方式相同。如果您正在尝试更新进度条或您不应该跨线程调用的东西。而是对 UI 线程以特定时间间隔读取的进度变量使用互锁写入。
和
是的,可以有任意长的延迟。 Invoke 通过向目标控件发送 Windows 消息来工作,因此它只会在目标线程发送消息时得到处理。如果线程已经在处理一条消息,并且该处理需要时间,那么在线程抽取其下一条消息并因此处理 Invoke 之前可能会有明显的延迟。
所以我需要找到另一个解决方案,比如等待 BeginInvoke 方法完成!
编辑:
如果我插入一些 thread.sleep() 语句,它似乎可以工作。可能是使用的定时器有问题。该定时器由读取线程启动,如果超过则触发事件:
阅读线程:
private void ReadThread()
{
FTDI.FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OK;
UInt32 numBytesAvailable = 0;
while (true)
{
ftStatus = myFtdiDevice.GetRxBytesAvailable(ref numBytesAvailable);
if (ftStatus == FTDI.FT_STATUS.FT_OK)
{
// read data and start timer
TimeoutWaitForAckn.Start();
}
}
}
然后,如果定时器超时则触发事件。 sleep 语句说明了这一点:
private void Timeout_Handler(object sender, System.Timers.ElapsedEventArgs e)
{
Thread.Sleep(300);
Trigger_ReportBufferReceivedEvent(ReceiveBuffer);
}
关于线程、计时器和事件,是否存在任何已知问题?使用 System.Timers.Timer。
最佳答案
我认为我们无法在不知道您的应用程序其余部分的情况下帮助您处理我们无法编译或运行的代码片段。
我已尝试重现您描述的问题,但恐怕它没有发生。我有 posted my code here in case you want to try it too (它实际上与您的代码相同)。该代码显示了一个带有进度条和按钮的表单。您单击该按钮,进度条在 10 秒内一直上升到 100%。一旦到达结尾,Debugger.Break()
就会触发。
如果您可以将上述代码更改为实际重现您的问题的代码,并将其作为独立示例发布,那么我们将能够为您提供帮助。
关于c# - 进度条行为异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4981109/