zoukankan      html  css  js  c++  java
  • 【转】浅述WinForm多线程编程与Control.Invoke的应用

    环境:VS2008、C#3.0

    在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来。一个最直接的方法便是使用多线程。多线程编程的方式在WinForm开发中必不可少。

    本文介绍在WinForm开发中如何使用多线程,以及在线程中如何通过Control.Invoke方法返回窗体主线程执行相关操作。

    -. WinForm多线程编程
    1. new Thread()
        新开一个线程,执行一个方法,没有参数传递:

    private void DoWork() {
                Thread t = new Thread(new ThreadStart(this.DoSomething));
                t.Start();
     }
    private void DoSomething() {
                MessageBox.Show("thread start");
     }

    新开一个线程,执行一个方法,并传递参数:

    private void DoWork() {
                Thread t = new Thread(new ParameterizedThreadStart(this.DoSomething));
                t.Start("guozhijian");
    }
    private void DoSomething(object o) {
                MessageBox.Show(o.ToString());
    }

    参数定义为object类型。

    2. ThreadPool
        众所周知,新开一个线程代价是很高昂的,如果我们每个操作都新开一个线程,那么太浪费了,于是,下面使用线程池。
        无参数传递:

    private void DoWork() {
                ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoSomething));
    }
    private void DoSomething(object o) {
                MessageBox.Show("thread start");
    }

    有参数传递:

    private void DoWork() {
                ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoSomething), "guozhijian");
    }
    private void DoSomething(object o) {
                MessageBox.Show(o.ToString());
    }

    使用匿名方法更灵活:

    private void DoWork() {
                string name = "guozhijian";
                ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object o){
                    MessageBox.Show(name);
                }));
    }

    在匿名代码段里面可以直接访问局部变量,不用在关心参数传递的问题

    二. Invoke
    1. this.Invoke
    现在,在业务线程里面执行完毕,要改变窗体控件的值了,此时,如果直接通过this得到控件的句柄,然后对它进行操作是会抛异常的,.Net WinForm Application里面是不允许这样的操作的。这是,可以调用Invoke方法

    2.Invoke方法签名:
    object Control.Invoke(Delegate Method)
    object Control.Invoke(Delegate Method, params object[] args)

    3.使用自定义委托

    private void DoWork() {
                WaitCallback wc = new WaitCallback(this.DoSomething);
                ThreadPool.QueueUserWorkItem(wc, "Guozhijian");
    }

    private delegate void MyInvokeDelegate(string name);

    private void DoSomething(object o) {
                this.Invoke(new MyInvokeDelegate(this.ChangeText), o.ToString());
    }

    private void ChangeText(string name) {
                this.textBox1.Text = name;
    }

    4.使用System.Action:

    private void DoWork() {
                WaitCallback wc = new WaitCallback(this.DoSomething);
                ThreadPool.QueueUserWorkItem(wc, "Guozhijian");
    }

    private void DoSomething(object o) {
                this.Invoke(new Action<string>(this.ChangeText), o.ToString());
    }

    private void ChangeText(string name) {
                this.textBox1.Text = name;
    }

    本例传递一个参数,System.Action有很多个重载,可以无参数(非泛型),而最多可以有四个参数,同样采用匿名方法,不使用泛型形式的System.Action,如下:

    private void DoWork() {
                WaitCallback wc = new WaitCallback(this.DoSomething);
                ThreadPool.QueueUserWorkItem(wc, "Guozhijian");
    }

    private void DoSomething(object o) {
                this.Invoke(new Action(delegate() {
                    this.textBox1.Text = o.ToString();
                }));
    }

    5.使用System.Func
    如果Invoke调用主窗体操作之后,还希望在调用完得到一个返回值:

    private void DoWork() {
                WaitCallback wc = new WaitCallback(this.DoSomething);
                ThreadPool.QueueUserWorkItem(wc, "Guozhijian");
    }

    private void DoSomething(object o) {
                System.Func<string, int> f = new Func<string, int>(this.GetId);
                object result = this.Invoke(f,o.ToString());
                MessageBox.Show(result.ToString());
    }

    private int GetId(string name) {
                this.textBox1.Text = name;
                if (name == "Guozhijian") {
                    return 999;
                }
                else {
                    return 0;
                }
    }

    result的值为 999。
    System.Func同样有很多泛形重载,这里不赘述。

    6.关于Invoke的拥有者:Control
    本文例中都是用this来引用,这里this替换为窗体任何一个控件的句柄都是OK的,因为Control.Invoke含义是将方法委托给拥有该Control的线程去执行。

  • 相关阅读:
    windows中dos命令指南
    HDU 2084 数塔 (dp)
    HDU 1176 免费馅饼 (dp)
    HDU 1004 Let the Balloon Rise (map)
    变态杀人狂 (数学)
    HDU 2717 Catch That Cow (深搜)
    HDU 1234 开门人和关门人 (模拟)
    HDU 1070 Milk (模拟)
    HDU 1175 连连看 (深搜+剪枝)
    HDU 1159 Common Subsequence (dp)
  • 原文地址:https://www.cnblogs.com/dachuang/p/10444728.html
Copyright © 2011-2022 走看看