如何妥善保管,而在C#中传递信息更新了用户界面? [英] How to properly keep the UI updated while transferring packets in C#?

查看:153
本文介绍了如何妥善保管,而在C#中传递信息更新了用户界面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这种形式,产生一个新的线程,并开始监听,等待在一个循环的UDP数据包。我需要的是保持与接收的字节数更新的用户界面。

I have this form that spawns a new thread and starts listening and waiting for UDP packets in a loop. What I need is to keep the UI updated with the number of bytes received.

对于这一点,我已经安装,我会尽快的数据包是引发事件接收和传递接收作为参数的字节数。因为我不是在UI线程上运行,我不能简单地直接更新UI。下面是目前我在做什么:

For that, I have setup an event which I'll raise as soon as a packet is received and pass the number of bytes received as an argument. Since I'm not running on the UI thread, I cannot simply update the UI directly. Here's what I'm currently doing:

private void EVENTHANDLER_UpdateTransferProgress(long receivedBytes) {
    if(InvokeRequired) {
        Invoke(new MethodInvoker(() => {
            totalReceivedBytes += receivedBytes;
            Label.Text = totalReceivedBytes.ToString("##,0");
        }));
    }
}



不过,这仍然是在同一运行线程的数据包接收循环并不会返回到循环 - 和等待另一个包 - 直到 EVENTHANDLER_UpdateTransferProgress 方法的返回值

But this is still running on the same thread as the packet reception loop and it will not return to that loop - and wait for another packet - until this EVENTHANDLER_UpdateTransferProgress method returns.

我的问题基本上是关于在上述方法中的以下行:

My question is basically about the following line in the method above:

Label.Text = totalReceivedBytes.ToString("##,0");



更新这样的UI减慢数据包的接收。如果我走这条线关闭(或评论的话),该数据包的接收会快很多。

Updating the UI like this slows down the packet reception. If I take that line off (or comment it), the packet reception will be much faster.

我怎么可能解决这个问题?我想更多的线程是关键,但我不知道如何正确地实施它们在这种情况下......我使用的是.NET 2.0 Windows窗体。

How can I possibly solve this issue? I think more threads is the key, but I'm not sure how to properly implement them in this situation... I'm using Windows Forms with .NET 2.0.

修改

在我以前的测试,上面似乎是真实的,它实际上可能是在一定程度上。而多了几分测试之后,我意识到这个问题是对整个调用(新MethodInvoker(()=> {...})); 的事情。当我删除(用户界面不会,当然更新),并留下 EVENTHANDLER_UpdateTransferProgress ,但不断提高的情况下,数据包接收的速度要快得多。

On my previous testing, the above seem to be true and it may actually be to some extent. But after a little more testing I realized the problem was on the whole Invoke(new MethodInvoker(() => { ... })); thing. When I remove that (the UI won't be updated of course) and leave EVENTHANDLER_UpdateTransferProgress but keep raising the event, the packet reception is much faster.

我测试得到了一些文件,它把平均约为〜1.5秒,而无需调用的invoke()在所有的事件处理程序。当我做呼叫的invoke()在事件处理程序,即使没有更新的用户界面的任何控制或做任何操作(换句话说,匿名方法体是空的)花了更长的时间,围绕〜5.5sec。你可以看到这是一个很大的区别。

I tested receiving some file which took in average about ~1.5sec without calling Invoke() at all on the event handler. When I did call Invoke() in the event handler, even without updating any control in the UI or doing any operation (in other words, the anonymous method body was empty), it took much longer, around ~5.5sec. You can see it's a big difference.

反正是有提高吗?

推荐答案

与方法的问题是,它更新上的每一个数据包的用户界面。如果您收到1000包每秒,你会更新UI每秒1000次!监视器可能不会刷新每秒超过100次,没有人会能够读取它,如果它每秒更新10次以上。

The problem with your approach is that it updates the UI on every single packet. If you received 1000 packets every second, you would update the UI 1000 times every second! The monitor probably doesn't refresh more than 100 times per second, and nobody is going to be able to read it if it updates more than 10 times per second.

一个更好的方式来处理这个问题是把 totalReceivedBytes + = receivedBytes; 在处理I / O,并把一个计时器,执行<$ c中的UI线程的线程$ C> Label.Text = totalReceivedBytes.ToString(##,0); 每秒只有几次最多。当传输开始时,开始计时;停止传输时,停止计时。

A better way to approach this problem is to put the totalReceivedBytes += receivedBytes; in the thread that handles the I/O and put a timer on the UI thread that executes Label.Text = totalReceivedBytes.ToString("##,0"); only a few times per second at most. When the transfer starts, start the timer; when the transfer stops, stop the timer.

这篇关于如何妥善保管,而在C#中传递信息更新了用户界面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆