代码之家  ›  专栏  ›  技术社区  ›  SLaks

在非UI线程上运行模式对话框

  •  6
  • SLaks  · 技术社区  · 15 年前

    我正在使用标准的.NET数据绑定编写一个简单的数据用户界面,该数据绑定来自SQL Server的类型化数据集。

    我有一个重新加载按钮 Fill 在所有数据适配器上获取数据库中的新数据(以防其他用户更改数据)。

    这需要一些时间,在此期间UI被冻结。它必须在UI线程上运行,或者数据绑定事件处理程序引发跨线程异常。

    当用户界面线程连接到数据库时,我想在后台线程上显示一个模式“请等待”对话框(以便可以对其进行动画处理)。

    如何在非UI线程上显示模式对话框?


    编辑: 我知道最佳实践是在后台运行操作,但由于数据绑定事件,我不能这样做。

    5 回复  |  直到 15 年前
        1
  •  8
  •   SLaks    15 年前

    你应该做相反的事情。在后台线程上运行长时间运行的进程,让UI线程空闲以响应用户操作。

    如果您想在处理过程中阻止任何用户操作,您有许多选项,包括模式对话框。后台线程完成处理后,可以将结果通知主线程。

        2
  •  2
  •   Jon Seigel    15 年前

    在数据绑定事件中运行的代码需要与UI分离,可能需要使用某种数据传输对象。

    然后可以在单独的线程或 BackgroundWorker ,并保留原来的UI线程。

    编辑:The 真的? 解决此问题的快速方法是使用 InvokeRequired .Invoke . 这将提供方法的UI上下文。我的同事做这件事就像是过时了,这件事总是让我很恼火,因为这样做很少是个好主意…但是,如果你想要一个快速的解决方案,这是可行的。(我不在工作,所以我没有带样品,我会设法想出一些办法。)

    编辑2:我不确定你想要什么是可能的。我制作了一个示例应用程序,它在另一个线程中创建了一个模式对话框,结果它是无模式的。您是否可以使用其他控件或控件集来指示进度更改,而不是使用模式对话框,最有可能直接在同一表单上?

        3
  •  0
  •   TcKs    15 年前
    using( var frmDialog = new MyPleasWaitDialog() ) {
        // data loading is started after the form is shown
        frmDialog.Load += (_sender, _e) {
            // load data in separate thread
            ThreadPool.QueueWorkItem( (_state)=> {
                myAdapter.Fill( myDataSet );
                // refresh UI components in correct (UI) thread
                frmDialog.Invoke( (Action)myDataControl.Refresh );
                // close dialog
                frmDialog.Invoke( (Action)frmDialog.Close() );
            }
        }
    
        // shows dialog
        frmDialog.ShowDialog( this );
    }
    
        4
  •  0
  •   t0mm13b    15 年前

    下面是一个使用BackgroundWorker加载数据的示例,并运行一个用户友好的表单来显示“加载记录”或类似的内容…

        public void Run()
        {
            bgWorkrFillDS = new BackgroundWorker();
            bgWorkrFillDS.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorkrFillDS_RunWorkerCompleted);
            bgWorkrFillDS.DoWork += new DoWorkEventHandler(bgWorkrFillDS_DoWork);
            bgWorkrFillDS.RunWorkerAsync();
        }
    
        void bgWorkrFillDS_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker bgWrkrFillDS = (BackgroundWorker)sender as BackgroundWorker;
            if (bgWrkrFillDS != null)
            {
                // Load up the form that shows a 'Loading....'
                // Here we fill in the DS
                // someDataSetAdapter.Fill(myDataSet);
            }
        }
    
    
        void bgWorkrFillDS_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // Hide or unload the form when the work is done
        }
    

    希望这有帮助… 当心, 汤姆。

        5
  •  0
  •   SLaks    15 年前

    我通过创建一个新的数据集,在后台加载,然后调用 DataSet.Merge 在UI线程上。谢谢大家的建议,这导致了这个解决方案。

    作为额外的奖励,这次跑步 许多的 比以前更快(呼叫 Fill 在后台,它只在没有打开网格的情况下工作)。有人知道为什么吗?