none
拜托:耗时操作中,如何立即更新UI界面? RRS feed

  • 问题

  • 1)如何实现ShowWait子程序。
    2)拜托给个简单的例子。
    3)不希望在Main中异步调用ProcSub。


    Sub Main()
      Call ShowWait("正在处理数据,请等待...")
      Call ProcSub()
      Call ShowWait("就绪")
    End Sub

    Sub ProcSub()
         '这里是一个非常耗时的子程序
       '可用System.Thread.Sleep(5000)模拟耗时操作
         '这个子程序可能会访问(读取)页面中的某些元素的属性
    End Sub

    Sub ShowWait(ByVal Msg As String)
      '这里要求更新SL页面中的某个元素的属性
          '比如:页面中有一个TextBlock,名称为TxtStatus,
          '如何更新其Text属性,并且其内容会在调用时立即显示,而不是等待Main运行结束后显示。
    End Sub

    2009年10月28日 17:31

答案

  • 你好,

    我知道你说的意思了.你可以在后台线程里做耗时的工作:

     public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();
        
            }

            public void ThreadPoolCallBack(Object threadContext)
            {
                //Do long time work here
                for (int i = 0; i < 5; i++)
                {
                    Thread.Sleep(1000);
                    Dispatcher.BeginInvoke(() => txtStatus.Text = DateTime.Now.ToString());
                }
                //Done
                Dispatcher.BeginInvoke(() => txtStatus.Text = "Done");
            }

            public void DoSthNeedLongTime() {
                ThreadPool.QueueUserWorkItem(ThreadPoolCallBack);         
            }
            public void ShowWait()
            {
                txtStatus.Text = "ShowWait Called";
            }

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                ShowWait();
                DoSthNeedLongTime();
              
            }

        }


    Please remember to mark the replies as answers if they help and unmark them if they provide no help. Welcome to the All-In-One Code Framework http://cfx.codeplex.com/! If you have any feedback, please tell us.
    2009年11月4日 9:30
    版主

全部回复

  • 用多线程做

    结束后别忘了回调UI线程,否则不能更新UI元素
    www.earan.com.cn/sl/ 是我们Earan Silverlight Team的Demo! 大家帮忙在Showcase上投票哈! http://silverlight.net/showcase/ 按照时间排序第11个。左边地区选中国,时间排序第1个
    2009年10月31日 7:52
  • 能否给个简单例子?
    2009年10月31日 8:11
  • 你好,

    你的意思是不是类似这样?

      public MainPage()
            {
                InitializeComponent();
                ThreadPool.QueueUserWorkItem(ThreadPoolCallBack);
                ShowWait();
            }

            public void ThreadPoolCallBack(Object threadContext)
            {
                while (true) {
                    Thread.Sleep(5000);
                    Dispatcher.BeginInvoke(()=>txtStatus.Text = DateTime.Now.ToString());
                }
           
            }
            public void ShowWait() {
                txtStatus.Text = "ShowWait Called";
            }


    Please remember to mark the replies as answers if they help and unmark them if they provide no help. Welcome to the All-In-One Code Framework http://cfx.codeplex.com/! If you have any feedback, please tell us.
    2009年11月4日 1:55
    版主
  • 谢谢回复。(本论坛其他人得回答不怎么准确,我还是比较喜欢你得回答)
    我的意思是,要求在耗时操作的过程中,不要等程序运行结束,就能立即刷新UI界面。
    另外:上次提到的DataGrid显示复杂的跨列表头的问题,通过HeaderStyle,CellTemplate得到了比较完美得解决。
    例如:
    Private Sub BtnTest_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles BtnTest.Click
        Call DoSth()
    End Sub

    Public Sub DoSth()
            '显示等待信息
            Call ShowWait()    '要求TxtStatus立即显示Processing Data, Please Wait....
             
            '调用耗时子程序
            Call DoSthNeedsLongTime()
           
            '显示结束信息
            Call HideWait()
    End Sub

    Public DoSthNeedsLongTime()
            '这里可能需要实际运行很长时间
            '这里也需要访问(读取)UI元素的有关属性
            '作为测试,这里只是模拟程序需要运行2秒。
            Dim T1 As Long = (Now().AddSeconds(2)).Ticks
            Do While (Now().Ticks) <= T1 : Loop
    End Sub

    '我就是想请教ShowWait怎么实现?
    Public ShowWait()
          '这样写,虽然TxtStatus的Text属性会改变,
          '但其UI界面并不会立即得到更新,实际上是要DoSth结束的时候,才会更新UI界面
          '我不明白这里应该怎么写
          TxtStatus.Text = "Processing Data, Please Wait...."
    End Sub

    Public Sub HideWait()
        TxtStatus.Text = "Ready"
    End Sub

    • 已编辑 TFSoft 2009年11月5日 3:02
    2009年11月4日 5:26
  • 你好,

    我知道你说的意思了.你可以在后台线程里做耗时的工作:

     public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();
        
            }

            public void ThreadPoolCallBack(Object threadContext)
            {
                //Do long time work here
                for (int i = 0; i < 5; i++)
                {
                    Thread.Sleep(1000);
                    Dispatcher.BeginInvoke(() => txtStatus.Text = DateTime.Now.ToString());
                }
                //Done
                Dispatcher.BeginInvoke(() => txtStatus.Text = "Done");
            }

            public void DoSthNeedLongTime() {
                ThreadPool.QueueUserWorkItem(ThreadPoolCallBack);         
            }
            public void ShowWait()
            {
                txtStatus.Text = "ShowWait Called";
            }

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                ShowWait();
                DoSthNeedLongTime();
              
            }

        }


    Please remember to mark the replies as answers if they help and unmark them if they provide no help. Welcome to the All-In-One Code Framework http://cfx.codeplex.com/! If you have any feedback, please tell us.
    2009年11月4日 9:30
    版主
  • 虽然可以实现,但是不是很理想。
    因为按提供的方法,需要调整程序的流程结构。
    我就需要按我给出的流程,实现ShowWaitMsg才好。

    这里有个关键的问题
    ThreadPoolCallBack 里面,其实我要调用界面元素,都得Dispatcher!!!
    2009年11月5日 2:47
  • 你好,

    由于要更新UI必须要让UI线程操作所以在其他线程中一定要用Dispatcher来做.这个应该是没有其他方法能够做到的. 费时的操作一般不推荐在UI线程上执行,因为会把UI hang住,降低用户体验.
    Please remember to mark the replies as answers if they help and unmark them if they provide no help. Welcome to the All-In-One Code Framework http://cfx.codeplex.com/! If you have any feedback, please tell us.
    2009年11月5日 3:16
    版主
  • 其实我的操作就是到服务器端取数据。
    注意:我用的是同步模式,不是异步模式。

    因此,我要的是如何在同步模式下,实现ShowWait
    2009年11月18日 11:33