【VB.NET2010】多线程程序编写技术分析

多线程,可以有效的避免慢速或者带有阻塞性质的代码的执行对窗体线程的影响。

比如一个死循环,如果在一个窗体中执行,则这个窗体就会出现我们称之为假死的现象,因为窗体的进程被用来处理死循环,而无法分开身去处理窗体消息和控件刷新重绘。所以,多线程在涉及外部设备连接,IO读取等等都会存在一些问题。


说完了使用多线程的原因,就该谈谈多线程的使用。

对于在VB6中混迹多年的码农,多线程是一个很高深高端高帅富的技术。而在VB.NET中,微软加强了VB的功能,让它和C#平起平坐,拥有相当的功能和相同的效率。


好了,闲话少叙,进入正题。

在VB.NET中,想使用多线程,就必须先定义一个线程类的对象,如下:

Dim thrScan As Threading.Thread
然后在启动线程之前,对线程进行初始化:

thrScan = New Threading.Thread(AddressOf StartScan)
这里的StartScan是线程将要执行的代码(函数Function、过程Sub)

这里的New就是创建对象初始化


然后就是启动线程了:

thrScan.Start()
在Start这个括号中,可以传入一个参数。只能是一个参数。但是,并没有限制类型。


为了分析和解决传递参数的问题,先分析下线程执行中的部分情况“

1、线程执行期间,线程可以读取控件中的值,比如获取文本框中的内容,等等。但是,无法直接写信息到控件,也无法直接修改控件的属性,除非设置一个CheckForIllegalCrossThreadCalls = False。否则会报错。有完美实现线程对窗体操作的,如委托。下面会有解介绍。

2、线程执行期间,窗体级变量,模块里面的全局变量,都可以被线程访问。

3、每个进程可能启动的是同一个过程,但是,每个过程中的变量,即使名字相同,在执行中也是不一样的。例如我启动一个线程1,线程2。线程1中的intKilo变量值为12,线程2中的这个intKilo的值可以为其他的值也可以为12,与线程1中的值无关。

4、启动线程的Start中的参数只能是一个,但是可以是几乎任何类型的。


基于以上四项,我们可以提出两套方案来解决多参量传输给进程作为启动参数的技术问题。

方案一:创建一个结构体,然后通过一个结构体变量来传递多个参数。

    Structure j
        Dim StartPath As String
        Dim StartTime As Date
        Dim ref As String
    End Structure
方案二:在启动新进程之前,将参数赋给几个全局变量。然后启动新线程,线程会根据全局变量的内容来创初始化。

'无示例代码

接下来,谈谈线程进行跨线程控件访问的解决方法:

对于线程,一般来讲是不允许直接在线程的代码中修改控件的内容,即不允许窗体修改。目的是避免两个线程同时修改窗体出现互锁(猜测)。但是,通过以下两种方法可以解决这个问题:

1、使用参数来禁止这种安全检查。

一般,在线程的代码头部,放入这么一句:

CheckForIllegalCrossThreadCalls = False
就可以像单线程程序一样进行控件的访问、控制、修改。这样是很方便,很偷懒,据说有一定的安全隐患。

2、使用委托。

委托这个东西从原理上我不是很清楚,但是使用上我还是可以给大家说说的,先给几个例子:

无参数的委托调用:

    Delegate Sub vClearList()
    Sub ClearList()
        ListView1.Items.Clear()
    End Sub

多参数的委托调用(单一参数同理):

    Delegate Sub vAddTopic(ByVal topic As String, ByVal url As String, ByVal count As Integer)
    Sub AddTopic(ByVal topic As String, ByVal url As String, ByVal count As Integer)
        Dim it As New ListViewItem
        it.Text = count
        it.SubItems.Add(topic)
        it.SubItems.Add(url)
        ListView1.Items.Add(it)
    End Sub

我们可以看出,首先,需要定义一个委托函数:

Delegate Sub 函数名(参数列表,如果有的话)

[Private|Public|Protected] Sub 函数名(参数列表,如果有的话)

建议这个参数列表最好是相同的。即函数本身的参数列表和委托函数的参数列表最好相同。


线程代码中,调用委托的方法:

1、无参数的委托调用

Invoke(New vStopButton(AddressOf StopButton))
即:Invoke(New 委托函数名(AddressOf 函数名))
2、有多个(含单个)参数的委托调用

Invoke(New vAddTopic(AddressOf AddTopic), topic, url, totalv)
即:Invoke(New 委托函数名(AddressOf 函数名),参数1,参数2,……,参数n) n≥1

我认为,使用委托的方式,等于将对控件的修改命令送入了队列,避免了同时修改的问题,由窗体的消息队列处理的单线程来进行,不会出现同时修改一个控件的问题。


欢迎大家批评指正留言!我几乎天天会看的。


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值