
多线程概述
进程和线程都是 *** 作系统的概念。进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭。
线程是进程内部的一个执行单元。系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说main或WinMain函数,将程序的启动点提供给Windows系统。主执行线程终止了,进程也就随之终止。
每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建的。用户根据需要在应用程序中创建其它线程,多个线程并发地运行于同一个进程中。每个线程具有自己的堆栈和自己的 CPU 寄存器副本。其他资源(如文件、静态数据和堆内存)由进程中的所有线程共享。所以线程间的通讯非常方便,多线程技术的应用也较为广泛。但是使用这些公共资源的线程必须同步。Win32 提供了几种同步资源的方式,包括信号、临界区、事件和互斥体。
每个进程都有私有的虚拟地址空间,进程的所有线程共享同一地址空间。每个线程被CPU分配一个时间片,一旦被激活,它正常运行直到时间片耗尽并被挂起,此时, *** 作系统选择另一个线程进行运行。通过时间片轮转,又出于各个时间片很小(20毫秒级),看起来就像多个线程同时在工作。实际上,只有在多处理器系统上才是真正的在可得到的处理器上同时运行多个线程。基于Win32的应用程序可以通过把给定进程分解(或创建)多个线程挖掘潜在的CPU时间,而且还可以加强应用程序,以使用户提高效率,加强反应能力以及进行后台辅助处理。
在Windows *** 作系统中,Win32应用程序可以在Windows平台上运行多个实例,每个应用程序实例都是一个独立的进程,而一个进程可以由不止一个线程来实现。对于一个进程来说,当应用程序有几个任务要同时运行时,建立多个线程是有用的。如打印时,利用多线程机制实现多线程,就可在需要打印时创建一个负责完成打印功能的打印线程。创建打印线程之后,系统就变成了多线程。当进行打印时,CPU轮换着分配给这两个线程时间片,所以打印和其他功能一起同时在运行,这就充分利用了CPU处理打印工作之外的空闲时间片,并且避免了用户长久地等待打印时间。这就是所谓的由多线程来实现的多任务,在进行打印任务的同时又可以进行别的任务。要说明的一点是,目前大多数的计算机都是单处理器(CPU)的,为了运行所有这些线程, *** 作系统为每个独立线程安排一些CPU时间, *** 作系统以轮换方式向线程提供时间片,这就给人一种假象,好象这些线程都在同时运行。由此可见,如果两个非常活跃的线程为了抢夺对CPU的控制权,在线程切换时会消耗很多的CPU资源,反而会降低系统的性能。这一点在多线程编程时应该注意。
Win32 SDK函数支持进行多线程的程序设计,并提供了 *** 作系统原理中的各种同步、互斥和临界区等 *** 作。Visual C++ 60中,使用MFC类库也实现了多线程的程序设计,线程被分为工作者线程(Worker Thread)和用户界面线程(User Interface Thread)两大类。前者常用于处理后台任务,执行这些后台任务并不会耽搁用户对应用程序的使用,即用户 *** 作无需等待后台任务的完成。后者常用来独立的处理用户输入和相应用户的事件。其中用户界面线程的特点是拥有单独的消息队列,可以具有自己的窗口界面,能够对用户输入和事件做出响应。在应用程序中,根据用户界面线程具有消息队列这一特点,可以使之循环等待某一事件发生后再进行处理。由于Windows95时抢先式多任务的 *** 作系统,即使一个线程因等待某事件而阻塞,其他线程仍然可以继续执行。
C#中的UI元素是主线程创建的,也只能通过创建它们的主线程进行修改,这是因为UI元素本身不是线程安全的,多线程 *** 作会发生不可预料的错误。因此,默认情况下,尝试从其他线程 *** 作UI元素会引发异常,虽然你可以通过下面的代码强制允许UI元素的跨线程 *** 作:1
CheckForIllegalCrossThreadCalls = false;
但是,这样做是不推荐的。一般对于UI元素的跨线程 *** 作推荐使用
1
2
FormInvoke(Delegate method);
FormInvoke(Delegate method, params object[] args);
Invoke方法可以由任何线程调用,但只会在创建Form的主线程上执行相应的Delegate。
一段最简示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
private void button1_Click(object sender, EventArgs e)
{
new SystemThreadingThread(ThreadAction)Start(); //启动线程
}
private void ThreadAction()
{
thisInvoke(new MethodInvoker(UIAction)); //在主线程上执行UIAction方法
}
private void UIAction()
{
thisText = "Invoked"; //不会报错
}
因为Invoke的参数包括Delegate委托,因此你需要根据要Invoke的方法的参数、返回值,定义对应的Delegate,然后才能调用。在上面的例子中,UIAction方法无参数、无返回,所以直接使用了MethodInvoker这个自带的Delegate。
以上就是关于“多线程”的原理是什么全部的内容,包括:“多线程”的原理是什么、c#windows应用程序怎么实现多线程、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)