进度条表现异常

3

我刚刚用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: 好的,我想我明白了。问题在于使用invoke方法处理跨线程。我在SO上找到了这句话:

不,至少对于Windows来说,这是任何UI的基础。Windows Forms中的消息架构并不新鲜,即使是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。


3
WinForms、WPF还是Silverlight? - John Saunders
(如果是WinForms)您是否考虑到PerformStep会按照ProgressBarStep属性所给定的数量进行推进,而该属性默认为10而不是1 - Timwi
1个回答

0

我认为我们无法帮助您处理一段无法编译或运行的代码片段,而且不知道您应用程序的其余部分。

我尝试重现您描述的问题,但恐怕没有发生。我已经在此处发布了我的代码,以便您也可以尝试(它与您的代码实际上是相同的)。该代码显示一个带有进度条和按钮的表单。您单击按钮,进度条在10秒内完全达到100%。一旦到达末端,Debugger.Break()将触发。

如果您能将上述代码更改为实际复制您的问题,并将其作为自包含示例发布,则我们将能够帮助您。


我认为代码本身太复杂了,而且贴在这里也太多了,所以我试图提取相关的部分。但是如果你的例子能正常工作,那么软件的另一部分可能存在问题... - binaryguy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接