跨线程操纵winform控件 [英] manipulating winform controls across threads

查看:88
本文介绍了跨线程操纵winform控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,


我正在尝试使用Invoke()进行多线程以设置Window Form控件的值,我需要一些帮助。


情况就是这样。我有一个表格上有很多控件。有一个"连接"此表单上的按钮。单击此按钮时,它会尝试连接到可能需要一段时间的数据库。因此,我们希望在连接时使用进度条调出一个新形式


但是,我已经了解到,为了使这个表单/进度条能够正常工作(具体来说,为了防止它隐藏在主应用程序表单后面并立即开始动画进度条),它需要在与数据库连接的
的单独线程中运行,具体而言,它必须在主线程中运行,同时数据库连接工作在新线程中完成。


到目前为止,这并不是太困难。当进行数据库连接的新线程必须操纵表单上的控件(带有"connect"按钮的控件)并且我得到一个跨线程操作错误时,会遇到困难。这个
是我需要一些指导的部分。


大多数例子都以检查InvokeRequired开头(如下所示:if(control.InvokeRequired){//在这里调用}) 。然而,我遇到的一个问题是我使用的控件没有InvokeRequired标志(我正在使用Telerik控件)。所以改为
我试图检测我是否在主线程上。这可能不是最好的方法,但它就是我现在所处的位置。在这一点上,我需要一些关于如何操作跨线程控件的指导,特别是当InvokeRequired
不可用时。


以下是我所拥有的一些代码:


[code]

//完成工作的功能:

         private void PopulateConnectionNameListView(String currentdatabase,bool mayInvoke = true)

        {


            if(mayInvoke&& System.Threading.Thread.CurrentThread.ManagedThreadId!= 1)//这是主线程吗?

             {

   //然后更好地调用:

             ;    this.Invoke(新的MethodInvoker(委托{PopulateConnectionNameListView(currentdatabase,false);}));
$
                返回;

            }


     //这是需要调用的行。
            radListViewConnectionName.Items.Clear();

...

}

[/ code]


[code]

  //以下是在后台进行数据库连接的工作人员功能:

         private void BackgroundWorker_DoWork(object sender,EventArgs e)

        {

            ConnectToSelectedDB(); //这是工作的主要切入点。它最终将调用PopulateConnectionNameListView()

        }


        private void BackgroundWorker_WorkCompleted(object sender,EventArgs e)

        {

        }
[/ code]


[code]

//这是连接按钮的按钮点击处理程序:

        private void radButtonConnection_Click(object sender,System.EventArgs e)

        {

            System.ComponentModel.BackgroundWorker bw = new System.ComponentModel.BackgroundWorker();

            bw.DoWork + = new System.ComponentModel.DoWorkEventHandler(BackgroundWorker_DoWork);

            bw.RunWorkerCompleted + = new System.ComponentModel.RunWorkerCompletedEventHandler(BackgroundWorker_WorkCompleted);

            bw.RunWorkerAsync();


     //这是我用进度条打开对话框的地方:
$
            frmRadWaitDialog waitDialog = new frmRadWaitDialog();

            waitDialog.Show();

        } b $ b [/ code]

解决方案

请查看这个帖子吗?


https://social.msdn.microsoft.com/Forums/vstudio/en-US/714efc63-1aea-4d30-ba18 -75d1444a91ba / C-如何-可以-I-复制一个文件夹与 - 进度?论坛= csharpgeneral#47c6ea84-e1cf-4245-841e-674b521b23d1


Hello,

I'm trying to do some multithread using Invoke() in order to set the values of Window Form controls, and I need some help.

The situation is this. I have a form on which there are many controls. There is a "connect" button on this form. When this button is clicked, it attempts to connect to a database which can take a while. Therefore, we want to bring up a new form with a progress bar while it is connecting.

I have learned, however, that in order for this form/progress bar to work properly (specifically, to prevent it from hiding behind the main application form and to start animating the progress bar immediately), it needs to run in a separate thread from that which does the database connecting, and specifically it has to run in the main thread while the database connecting work in done in a new thread.

So far, this has not been too difficult. The difficulty comes in when the new thread which does the database connecting has to manipulate the controls on the form (the one with the "connect" button) and I get a cross-thread operation error. This is the part I need some guidance on.

Most examples start with a check on InvokeRequired (like this: if (control.InvokeRequired) { // invoke here }). One of the problems I'm having, however, is that the controls I'm using don't have the InvokeRequired flag (I'm using Telerik controls). So instead I'm trying to detect if I'm on the main thread or not. This may not be the best method, but it's kind of where I'm at right now. It's at this point that I need some guidance on how to manipulate controls from across threads, especially when InvokeRequired is not available.

Here's some of the code I have in place:

[code]
// Function that does the work:
        private void PopulateConnectionNameListView(String currentdatabase, bool mayInvoke = true)
        {

            if (mayInvoke && System.Threading.Thread.CurrentThread.ManagedThreadId != 1) // is this the main thread?
            {
  // Then better invoke:
                this.Invoke(new MethodInvoker(delegate { PopulateConnectionNameListView(currentdatabase, false); }));
                return;
            }

     // This is the line that requires invoking
            radListViewConnectionName.Items.Clear();
...
}
[/code]

[code]
 // Here are the worker functions that do the database connecting in the background:
        private void BackgroundWorker_DoWork(object sender, EventArgs e)
        {
            ConnectToSelectedDB(); // This is the main entry point for the work. It will eventually call PopulateConnectionNameListView()
        }

        private void BackgroundWorker_WorkCompleted(object sender, EventArgs e)
        {
        }
[/code]

[code]
// Here's the button click handler for the connect button:
        private void radButtonConnection_Click(object sender, System.EventArgs e)
        {
            System.ComponentModel.BackgroundWorker bw = new System.ComponentModel.BackgroundWorker();
            bw.DoWork += new System.ComponentModel.DoWorkEventHandler(BackgroundWorker_DoWork);
            bw.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(BackgroundWorker_WorkCompleted);
            bw.RunWorkerAsync();

     // Here's where I bring up my dialog with the progress bar:
            frmRadWaitDialog waitDialog = new frmRadWaitDialog();
            waitDialog.Show();
        }
[/code]

解决方案

Can you please check this thread?

https://social.msdn.microsoft.com/Forums/vstudio/en-US/714efc63-1aea-4d30-ba18-75d1444a91ba/c-how-can-i-copy-a-folder-with-progressbar?forum=csharpgeneral#47c6ea84-e1cf-4245-841e-674b521b23d1


这篇关于跨线程操纵winform控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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