C#多线程开发

1 篇文章 0 订阅

1. 引言

最近,正在进行一个基于C# WinForm的上位机软件的开发与调试工作。项目中遇到一个问题:对画框在在执行某种操作的时候,主界面的显示数据不再更新,直到业务执行完毕。借助多线程,可以很好的解决这个问题,实现并发执行。

使用多线程,可以实现代码的隔离和并发执行,提高应用程序的可靠性和执行效率。

2. 多线程编程

(1)通过委托传递线程函数

线程函数通过委托传递,委托有两种:不带参数的ThreadStart和带参数的ParameterizedThreadStart。

// 不能传递参数,也不能有返回值
ThreadStart threadStart =new ThreadStart(this.DoSomething);
Thread t1 = new Thread(threadStart);
t1.Start();

// 可以传递一个参数,但不能有返回值
ParameterizedThreadStart paramThreadStart = new ParameterizedThreadStart(this.DoSomething);
Thread t2 = new Thread(paramThreadStart);
t2.Start("Parameter");

// 传递匿名方法,可以实现多个参数和返回值的效果
int param = 100;
int ret = 0;
ThreadStart noNameStart =new ThreadStart(delegate()
{
    ret = param * 10;
});
Thread t3 = new Thread(threadStart);
t3.Start();

(2)使用专门的线程类传递线程函数

线程函数通过自定义线程类传递,可以实现传递任意数目参数和返回值。


(3)使用委托开启多线程

上面两种方式虽然利用不同的形式传递线程函数,但开启线程都采用线程对象的Start方法开启线程。这里介绍一种通过委托开启线程的方法。

(未完待续)

(4)使用线程池

过多线程的创建和销毁会较多的内存消耗,这时候可以考虑使用线程池。线程池维护一个请求队列,线程池的代码从队列提取任务,然后委派给线程池的一个线程执行。线程执行完并不会立即销毁,这样既可以后台执行任务,又可以减少线程创建和销毁的开销 。

使用方法如下:

// 带参数
WaitCallback wc1 = new WaitCallback(this.DoSomething);
ThreadPool.QueueUserWorkItem(wc1);

// 不带参数
WaitCallback wc2 = new WaitCallback(this.DoSomething);
ThreadPool.QueueUserWorkItem(wc2, "Parameter");

3. 避免跨线程更新UI

跨线程更新UI是写多线程程序尤其是通信类程序经常遇到的问题,这里面主要的问题是冲突,比如数据线程想要更新UI的时候,用户线程同时也在更新UI。解决这个问题主要有两种方法:

(1)关闭跨线程监测

// 关闭跨线程监测
Control.CheckForIllegalCrossThreadCalls = false;

这种方式有一定的风险,容易使程序崩溃。

(2)使用Invoke

private void UpdateText(string strParam)
{
	// 当前线程是创建线程(界面线程)
	if (myControl.InvokeRequired)
	{
		// 利用委托更新
		myControl.Invoke(new InvokeDelegate(UpdateText), new object[]{strParam});
	}
	else
	{
		// 直接更新
		myControl.Text = strParam;
	}
}

判断当前线程是不是控件的创建线程,如果是就直接更新,否则就建立一个Invoke对象,设置好代理和参数,然后再调用Invoke。

(3)使用自定义委托

ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoSomething), new object());
private void DoSomething(object o)
{
    // MyInvokeDelegate为自定义委托
    this.Invoke(new MyInvokeDelegate(UpdateText), o.ToString());
}

(4)使用System.Action

ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoSomething), new object());
private void DoSomething(object o)
{
    // 传递一个参数的命名方法
    this.Invoke(new Action<string>(UpdateText, o.ToString()));
    // 匿名方法
    this.Invoke(new Action(delegate(){this.textBox.Text = o.ToString();}));
}
System.Action有多个重载,可以无参数,最多可以有4个参数,还可以采用匿名方法,但是没有返回值。

(5)使用System.Func

ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoSomething), new object());
private void DoSomething(object o)
{
    // 在Invoke调用主窗体操作后,还可以得到一个返回值
    object result = this.Invoke(new Func<string, int>(this.NameToCode), o.ToString());
}

System.Func与System.Action类似,同样有很多泛型重载,最多可以有16个参数,且必须有返回值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值