c# 线程运用

      Windows系列操作系统是建立在保护模式之上的32位/64位多任务操作系统,其特点是:时分抢先式多任务操作系统。我们来详细探讨一下其中的定义
Windows操作系统是如何来启动一个应用程序(.exe文件):
       操作系统分配一个进程,并向CPU下达一系列指令,包括创建该进程的虚拟内存映射表(关于虚拟内存,请参阅操作系统原理相关书籍,32位保护模式这一概念),分配虚拟内存,设定进程描述符等等,最终将进程封闭到一个独立的虚拟内存地址空间中,返回进程句柄; 操作系统为该进程创建一个线程,并启动它; 该线程从应用程序的Main方法开始执行。 也即是说,所有的Windows进程,都缺省拥有一个线程,这个线程称为主线程;主线程可以根据代码要求创建其它线程,称为辅助线程。

 

操作系统是如何在CPU上调度多个线程:
    Windows操作系统采用了“时分”的概念来调度多个线程,即每个线程占用CPU一段时间后,就会被强行将执行权交给下一个线程。线程轮流来使用CPU。使用CPU的线程,正常执行程序,时间到达时,操作系统执行线程切换操作:将CPU寄存器的内容全部转移到内存中,将另一个线程保存的寄存器状态从内存恢复到寄存器中,由于寄存器中保存了某个线程正在运行哪一行代码的指针,所以切换后另一个线程可以继续上一次运行状态继续运行。这种切换线程的方式称为:现场保存和现场恢复。


控制线程的Thread类和方法
Thread.Start()方法:
开始线程
Thread.IsAlive 属性:
如果此线程已启动并且尚未正常终止或中止,则为 true;否则为 false。
Suspend():该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复;
Resume():恢复被Suspend()方法挂起的线程的执行。
Thread.ThreadState 属性
     Aborted:线程已停止;
     AbortRequested:线程的Thread.Abort()方法已被调用,但是线程还未停止;
     Background:线程在后台执行,与属性Thread.IsBackground有关;不妨碍程序的终止
     Running:线程正在正常运行;
     Stopped:线程已经被停止;
     StopRequested:线程正在被要求停止;
     Suspended:线程已经被挂起(此状态下,可以通过调用Resume()方法重新运行);
     SuspendRequested:线程正在要求被挂起,但是未来得及响应;
     Unstarted:未调用Thread.Start()开始线程的运行;
     WaitSleepJoin:线程因为调用了Wait(),Sleep()或Join()等方法处于封锁状态;

线程的优先级
     由高到低分别是Highest,AboveNormal,Normal,BelowNormal,Lowest;系统默认为ThreadPriority.Normal
     指定优先级的代码:myThread.Priority=ThreadPriority.Lowest;

多线程的优劣
     优点:可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。
     缺点:线程也是程序,所以线程需要占用内存,线程越多占用内存也越多;
           多线程需要协调和管理,所以需要CPU时间跟踪线程;
           线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;
           线程太多会导致控制太复杂,最终可能造成很多Bug;

 


如何的安全的退出线程:
    按照要求,无论使用何种编程语言,线程都必须自然退出,而不应该被迫退出。所谓自然退出。在.net Framework中没有提供任何可以杀死线程的方法,所以我们只能等待线程执行完毕后自然死亡。
    I/强制杀死线程(非安全)....Abord方法:停止线程的执行
     在一个线程中停止另一个线程的执行,此时被终止的线程立即抛出一个ThreadAbortException异常,通过抛出异常跳出线程代码执行。通过try…catch(ThreadAbortException)…段包围线程方法内的代码,可以在线程被中止后得到一个通知。
    I/设置一段时间等待线程之后再调用Abord方法(安全)...Join方法:等待该线程终止。
    在一个父线程(如主线程)调用Join,等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。(Waits for this thread to die.)
 

 

**对于在线程中使用Control类的Invoke方法通过委访问行窗体或控件方法或属性的情况,还有几点注意事项:
I/   窗体不能先于线程销毁。当线程代码运行到Invoke方法时,如果窗体已经被关闭,则会引发异常。此时,窗体必须等待并确保线程确实退出了才能关闭;
II/  不能在创建窗体的线程(一般为主线程)中等待辅助线程结束(调用线程对象的Join方法),因为调用了Join方法的线程会被阻塞(即不再向下运行,而在Join方法上等待),而Invoke方法会向窗体所在线程的消息循环发送执行委托的消息,窗体线程被阻塞后消息循环也会被阻塞(除非调用:Application.DoEvents();//主动调用消息循环 ),Invoke方法自然也会被阻塞,结果就是窗体线程和辅助线程均被阻塞,程序进入死锁;

 

!!!Delegate.Invoke是相当于直接调用。
!!!Control.Invoke是SendMessage,将当前操作同步到界面线程的。 所以我们在Control.Invoke的代理函数尽量不要使用阻滞线程的操作,因为当前线程是主线程。


III/ 解决上述问题的方法很简单:在窗体关闭事件中取消窗体关闭(e.Cancel)并启动一个辅助线程来等候其它辅助线程结束(第64-80行),并在等候成功后由该线程通过委托方法来关闭窗体。用辅助线程来等待其它辅助线程结束,则不会阻塞窗体线程,等待成功后关闭窗体,则可以保证窗体在这些线程退出后才安全关闭。

  

设置前台线程和后台线程
   前台线程(Thread类默认为前台线程):即该线程会阻止进程结束。即便主线程结束了,只要进程中还有一个前台线程尚未结束,则进程不会结束,直到所有的前台线程都结束。这是最安全的一种方式,保证线程在结束前做完其所有工作。
   后台线程(不涉及I/O操作的线程)-既IsBackground=True :只要主线程退出,这些线程就会被强制结束。
http://msdn.microsoft.com/zh-cn/library/7a2f3ay4(VS.80).aspx

------------------------
BackgroundWorker--后台操作控件
★BackgroundWorker实现WinForm异步操作/演练:在后台运行操作
如果有一个需要很长时间才能完成的操作,而且不希望用户界面中出现延迟,则

可以使用

BackgroundWorker 类来在另一个线程上运行该操作。
事件:
1,ReportProgress的调用将会导致ProgressChanged事件被触发。

ProgressChanged event handler用于

显示当前进度、当前记录数量和显示获取的纪录:

2,如何操作正常地结束,BackgroundWorker的RunWorkerCompleted会被触发
注:如果操作需要操作UI上的控件,只能在Main Thread中进行。如何在

RetrieveData方法进行的话,由

于该方式是一个异步方法,是会抛出异常的。
方法:
1,this.backgroundWorkerLeft.RunWorkerAsync(object);//开始
RunWorkerAsync方法被掉调用,我们定义的常量(object )当作参数被掺入。随

后,将会触发其DoWork

事件
this.backgroundWorkerLeft.CancelAsync();//手工结束掉当前的操作
 

------------------------------------------------------------------------

多线程 实现返回值 任意参数

1,使用委托异步

2,


http://hi.baidu.com/ccm_8730/blog/item/626f95091c81e82d6a60fb38.html

C# 多线程在实际场景中有广泛的应用,以下是一些实际应用案例和使用方法: ### 实际应用案例 - **提高程序响应性**:在桌面应用程序中,为了避免长时间运行的任务阻塞用户界面线程,可使用多线程。例如,在一个图片处理软件中,用户点击某个处理按钮后,软件需要对图片进行复杂的滤镜处理。若将这个处理任务放在主线程中,界面会卡顿,用户无法进行其他操作。此时可开启一个新线程来执行图片处理任务,主线程继续响应用户的其他操作,如关闭窗口、切换菜单等。 - **并行计算**:在科学计算和数据处理领域,多线程可用于并行计算,充分利用多核处理器的性能。例如,在一个数据分析程序中,需要对大量的数据进行统计分析,可将数据分成多个部分,每个线程负责处理一部分数据,最后将结果汇总,从而大大提高计算速度。 - **网络编程**:在网络服务器程序中,多线程可用于同时处理多个客户端的请求。例如,一个简单的 TCP 服务器,当有客户端连接时,可开启一个新线程来处理该客户端的请求,这样服务器就能同时处理多个客户端的连接和数据交互,提高服务器的并发处理能力。 ### 使用方法 - **显示线程信息**:可通过 `Thread` 类的属性来获取当前线程的信息,如线程 ID、线程名称等。示例代码如下: ```csharp using System; using System.Threading; class Program { static void Main() { Thread currentThread = Thread.CurrentThread; Console.WriteLine($"线程 ID: {currentThread.ManagedThreadId}"); Console.WriteLine($"线程名称: {currentThread.Name}"); } } ``` - **线程的基本使用**:使用 `Thread` 类创建和启动一个新线程。示例代码如下: ```csharp using System; using System.Threading; class Program { static void ThreadMethod() { Console.WriteLine("新线程开始执行"); // 模拟一些工作 Thread.Sleep(2000); Console.WriteLine("新线程执行结束"); } static void Main() { Thread newThread = new Thread(ThreadMethod); newThread.Start(); Console.WriteLine("主线程继续执行"); newThread.Join(); Console.WriteLine("主线程执行结束"); } } ``` - **线程同步**:使用 `lock` 关键字来实现线程同步,确保多个线程对共享资源的访问是安全的。示例代码如下: ```csharp using System; using System.Threading; class Program { private static readonly object lockObject = new object(); private static int sharedResource = 0; static void Increment() { for (int i = 0; i < 100000; i++) { lock (lockObject) { sharedResource++; } } } static void Main() { Thread thread1 = new Thread(Increment); Thread thread2 = new Thread(Increment); thread1.Start(); thread2.Start(); thread1.Join(); thread2.Join(); Console.WriteLine($"共享资源的值: {sharedResource}"); } } ``` - **线程池的使用**:为了避免频繁创建和销毁线程带来的性能开销,可使用线程池。示例代码如下: ```csharp using System; using System.Threading; class Program { static void ThreadPoolMethod(object state) { Console.WriteLine($"线程线程开始执行,状态: {state}"); // 模拟一些工作 Thread.Sleep(2000); Console.WriteLine("线程线程执行结束"); } static void Main() { ThreadPool.QueueUserWorkItem(ThreadPoolMethod, "数据"); Console.WriteLine("主线程继续执行"); Thread.Sleep(3000); Console.WriteLine("主线程执行结束"); } } ``` ### 注意事项 在使用 C# 多线程时,需要注意线程安全、死锁、性能开销和异常处理等问题。可使用锁(`lock`)、`Monitor` 类、`Mutex`、`Semaphore`、`ReaderWriterLockSlim` 等机制来实现线程同步,避免多个线程相互等待对方释放资源导致死锁,尽量重用线程(例如使用线程池)以减少性能开销,并确保对异常进行适当的处理,避免未捕获的异常导致应用程序崩溃 [^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值