• C# 以ThreadStart方式实现多线程


     

    3.1 使用ThreadStart委托

    这 里先以一个例子体现一下多线程带来的好处,首先在Message类中建立一个方法ShowMessage(),里面显示了当前运行线程的Id,并使用 Thread.Sleep(int ) 方法模拟部分工作。在main()中通过ThreadStart委托绑定Message对象的ShowMessage()方法,然后通过 Thread.Start()执行异步方法。

     1       public class Message
     2       {
     3           public void ShowMessage()
     4           {
     5               string message = string.Format("Async threadId is :{0}",
     6                                               Thread.CurrentThread.ManagedThreadId);
     7               Console.WriteLine(message);
     8   
     9               for (int n = 0; n < 10; n++)
    10               {
    11                   Thread.Sleep(300);   
    12                   Console.WriteLine("The number is:" + n.ToString()); 
    13               }
    14           }
    15       }
    16   
    17       class Program
    18       {
    19           static void Main(string[] args)
    20           {
    21               Console.WriteLine("Main threadId is:"+
    22                                 Thread.CurrentThread.ManagedThreadId);
    23               Message message=new Message();
    24               Thread thread = new Thread(new ThreadStart(message.ShowMessage));
    25               thread.Start();
    26               Console.WriteLine("Do something ..........!");
    27               Console.WriteLine("Main thread working is complete!");
    28               
    29           }
    30       }
    请注意运行结果,在调用Thread.Start()方法后,系统以异步方式运行Message.ShowMessage(),而主线程的操作是继续执行的,在Message.ShowMessage()完成前,主线程已完成所有的操作。

    3.2 使用ParameterizedThreadStart委托

    ParameterizedThreadStart 委托与ThreadStart委托非常相似,但ParameterizedThreadStart委托是面向带参数方法的。注意 ParameterizedThreadStart 对应方法的参数为object,此参数可以为一个值对象,也可以为一个自定义对象。

     1     public class Person
     2     {
     3         public string Name
     4         {
     5             get;
     6             set;
     7         }
     8         public int Age
     9         {
    10             get;
    11             set;
    12         }
    13     }
    14 
    15     public class Message
    16     {
    17         public void ShowMessage(object person)
    18         {
    19             if (person != null)
    20             {
    21                 Person _person = (Person)person;
    22                 string message = string.Format("
    {0}'s age is {1}!
    Async threadId is:{2}",
    23                     _person.Name,_person.Age,Thread.CurrentThread.ManagedThreadId);
    24                 Console.WriteLine(message);
    25             }
    26             for (int n = 0; n < 10; n++)
    27             {
    28                 Thread.Sleep(300);   
    29                 Console.WriteLine("The number is:" + n.ToString()); 
    30             }
    31         }
    32     }
    33 
    34     class Program
    35     {
    36         static void Main(string[] args)
    37         {     
    38             Console.WriteLine("Main threadId is:"+Thread.CurrentThread.ManagedThreadId);
    39             
    40             Message message=new Message();
    41             //绑定带参数的异步方法
    42 Thread thread = new Thread(new ParameterizedThreadStart(message.ShowMessage)); 43 Person person = new Person(); 44 person.Name = "Jack"; 45 person.Age = 21; 46 thread.Start(person); //启动异步线程
    47 48 Console.WriteLine("Do something ..........!"); 49 Console.WriteLine("Main thread working is complete!"); 50 51 } 52 }
    运行结果:

    3.3 前台线程与后台线程

    注意以上两个例子都没有使用Console.ReadKey(),但系统依然会等待异步线程完成后才会结束。这是因为使用Thread.Start()启动的线程默认为前台线程,而系统必须等待所有前台线程运行结束后,应用程序域才会自动卸载。

    在第二节曾经介绍过线程Thread有一个属性IsBackground,通过把此属性设置为true,就可以把线程设置为后台线程!这时应用程序域将在主线程完成时就被卸载,而不会等待异步线程的运行。

    3.4 挂起线程

    为了等待其他后台线程完成后再结束主线程,就可以使用Thread.Sleep()方法。

     1     public class Message
     2     {
     3         public void ShowMessage()
     4         {
     5             string message = string.Format("
    Async threadId is:{0}",
     6                                            Thread.CurrentThread.ManagedThreadId);
     7             Console.WriteLine(message);
     8             for (int n = 0; n < 10; n++)
     9             {
    10                 Thread.Sleep(300);
    11                 Console.WriteLine("The number is:" + n.ToString());
    12             }
    13         }
    14     }
    15 
    16     class Program
    17     {
    18         static void Main(string[] args)
    19         {     
    20             Console.WriteLine("Main threadId is:"+
    21                               Thread.CurrentThread.ManagedThreadId);
    22             
    23             Message message=new Message();
    24             Thread thread = new Thread(new ThreadStart(message.ShowMessage));
    25             thread.IsBackground = true;
    26             thread.Start();
    27             
    28             Console.WriteLine("Do something ..........!");
    29             Console.WriteLine("Main thread working is complete!");
    30             Console.WriteLine("Main thread sleep!");
    31             Thread.Sleep(5000);
    32         }
    33     }

    运行结果如下,此时应用程序域将在主线程运行5秒后自动结束

    但 系统无法预知异步线程需要运行的时间,所以用通过Thread.Sleep(int)阻塞主线程并不是一个好的解决方法。有见及此,.NET专门为等待异 步线程完成开发了另一个方法thread.Join()。把上面例子中的最后一行Thread.Sleep(5000)修改为 thread.Join() 就能保证主线程在异步线程thread运行结束后才会终止。

    3.5 Suspend 与 Resume (慎用)

    Thread.Suspend() 与 Thread.Resume()是在Framework1.0 就已经存在的老方法了,它们分别可以挂起、恢复线程。但在Framework2.0中就已经明确排斥这两个方法。这是因为一旦某个线程占用了已有的资源, 再使用Suspend()使线程长期处于挂起状态,当在其他线程调用这些资源的时候就会引起死锁!所以在没有必要的情况下应该避免使用这两个方法。

    3.6 终止线程

    若想终止正在运行的线程,可以使用Abort()方法。在使用Abort()的时候,将引发一个特殊异常 ThreadAbortException 。
    若想在线程终止前恢复线程的执行,可以在捕获异常后 ,在catch(ThreadAbortException ex){...} 中调用Thread.ResetAbort()取消终止。
    而使用Thread.Join()可以保证应用程序域等待异步线程结束后才终止运行。

     1          static void Main(string[] args)
     2          {
     3              Console.WriteLine("Main threadId is:" +
     4                                Thread.CurrentThread.ManagedThreadId);
     5  
     6              Thread thread = new Thread(new ThreadStart(AsyncThread));
     7              thread.IsBackground = true;
     8              thread.Start();
     9              thread.Join();
    10  
    11          }     
    12          
    13          //以异步方式调用
    14 static void AsyncThread() 15 { 16 try 17 { 18 string message = string.Format(" Async threadId is:{0}", 19 Thread.CurrentThread.ManagedThreadId); 20 Console.WriteLine(message); 21 22 for (int n = 0; n < 10; n++) 23 { 24 //当n等于4时,终止线程
    25 if (n >= 4) 26 { 27 Thread.CurrentThread.Abort(n); 28 } 29 Thread.Sleep(300); 30 Console.WriteLine("The number is:" + n.ToString()); 31 } 32 } 33 catch (ThreadAbortException ex) 34 { 35 //输出终止线程时n的值
    36 if (ex.ExceptionState != null) 37 Console.WriteLine(string.Format("Thread abort when the number is: {0}!", 38 ex.ExceptionState.ToString())); 39 40 //取消终止,继续执行线程
    41 Thread.ResetAbort(); 42 Console.WriteLine("Thread ResetAbort!"); 43 } 44 45 //线程结束
    46 Console.WriteLine("Thread Close!"); 47 }

    运行结果如下

  • 相关阅读:
    sqlserver数据库的备份与还原——完整备份与还原
    sqlserver中为节约存储空间的收缩数据库机制
    sqlserver数据库的分离与附加
    sqlserver的数据库状态——脱机与联机
    sqlserver打开对象资源管理器管理的帮助文档的快捷键
    sqlserver使用SQL语句创建数据库登录对象、数据库用户以及对为该用户赋予操作权限
    sqlserver window身份验证时切换账户的快捷键
    向现有数据库中添加文件组和数据文件
    使用SQL语句创建数据库2——创建多个数据库文件和多个日志文件
    Java中怎样判断一个字符串是否是数字?
  • 原文地址:https://www.cnblogs.com/lvdongjie/p/5001062.html
Copyright © 2020-2023  润新知