发布博文
随想
读书
音乐
其他
我想爱,想吃,还想在一瞬间变成天上半明半暗的云。
我想爱,想吃,还想在一瞬间变成天上半明半暗的云。
我想爱,想吃,还想在一瞬间变成天上半明半暗的云。
我想爱,想吃,还想在一瞬间变成天上半明半暗的云。

跨线程调用windows窗体控件

645
高光翔
2018-11-01 19:43

helloworld.jpg

如果在新的线程中直接使用其它线程创建的windows窗体控件时,会报错误“线程间操作无效,不是从创建控件' '的线程访问它。”因为windows不允许从创建控件以外的线程调用控件。有两种方法可以实现非GUI线程调用控件。一种为基于TAP的异步编程方法,一种为使用Invoke、BeginInvoke的方法。

捕获.png

1. TAP异步方法

这种方法比较简单,也比较现代化,推荐使用这种方法,将click委托方法标记为async异步方法,使用Task取线程,直接可在Task委托内调用控件。待到异步线程执行到控件的调用时,状态机会交给GUI线程去处理。

        private async void button1_Click(object sender, EventArgs e)
        {
            await Task.Run(() =>
            {
                //异步线程中执行计算
                //...
                this.textBox1.Text = "ggx";
            });
        }

2. 使用Invoke(BeginInvoke)

控件的基类Control下提供的Invoke或BeginInvoke方法。将要对目标控件执行的操作写到委托中,然后将委托作为参数传递给BeginInvoke方法。创建一个窗体控件,在窗体控件中添加一个button按钮控件和一个textBox控件。点击按钮改变textBox的text值,为了说明问题,我们在新的线程中做改变textBox属性的工作。具体的代码和说明如下。

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            //创建一个action委托,将改变textBox值的过程写到委托中
            Action act = () =>
            {
                this.textBox1.Text = "ggx";
            };
            //创建一个新的线程
            Task task = new Task(() =>
            {
                //异步线程中执行计算
                //...
                //调用BeginInvoke方法,将委托传入
                this.BeginInvoke(act);
            });
            //启动线程
            task.Start();
        }
    }

参考:

https://www.cnblogs.com/darksoulson/p/3428577.html

https://blog.csdn.net/loverszhaokai/article/details/6071787

https://docs.microsoft.com/zh-cn/dotnet/framework/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls

Insert title here Insert title here
打  赏