日期:2014-05-18  浏览次数:21222 次

WPF vs WinForm 多线程UI跟新问题
写了个小小的测试程序,在Winform分别加了一个Winform的ProcessBar和WPF的ProcessBar,再加一个button, 下面是button Click事件的代码:
C# code
private void button1_Click(object sender, EventArgs e)
        {
            mWinformProgressBar.Value = 0;
            mWPFProcessBar.Value = 0;
            double d = 0.0f;
            for (int i = 0; i < 1000; i++)
            {
                for (int j = 0; j < 100000; j++)
                {
                    d = (double)i / (j + 1);
                }
                mWinformProgressBar.Value += 1;
                mWPFProcessBar.Value += 1;
            }
        }

个人先前预期的结果是: 界面没反应,两个ProcessBar都没有反应直到循环结束。
但实际运行结果有点出乎我的预料: 界面没反应,WPF的ProcessBar也没反应,但Winform的ProcessBar却能时时更新。谁能帮我解释下呢,能给出些相关的参考资料更好。

如果在每个小循环里加System.Windows.Forms.Application.DoEvents(), WPF的ProcessBar也能几时更新,我想知道有没有其他方法也能让WPF时时更新.(另起 System.Threading下的线程除外)

------解决方案--------------------
...
------解决方案--------------------
wpf下的多线程写法确实跟winform下的不一样,我当初平移winform下的时候就遇到过这个问题.
不过说实在的,具体什么原因我不是很懂,毕竟是做bs出身的,不过后来一个同事用一个叫什么dispatcher(名字可能有误)的东西实现了.
楼主可以用那个方法试一试,希望能帮到你.
------解决方案--------------------
不管是Winform还是WPF都应该加上System.Windows.Forms.Application.DoEvents()。

你试试在点击按钮后切换到另一个程序,再切换回来。如果没有加上这句,Winform会直到运行完毕才更新界面,加上这句切换回来时会继续显示进度条在前进。
------解决方案--------------------
mark
------解决方案--------------------
建议使用BackgroundWorker,楼主可以查查MSDN,上面有很多例子
------解决方案--------------------
都是循环中更新的问题。

Systems.DoEvents使用PeekMessage处理完消息队列,使UI有机会更新。

WPF中你可以往Dispatch里PushFrame达到同样的效果

C# code

public void DoEvents()
{
    DispatcherFrame frame = new DispatcherFrame();
    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
        new DispatcherOperationCallback(delegate(object f)
            {
                ((DispatcherFrame)f).Continue = false;

                return null;
            }
            ), frame);
    Dispatcher.PushFrame(frame);
}