线程

线程

线程应用场景:

(1):希望获得更多操作系统资源尽快处理我们的业务,缩短处理的时间

(2) 如果一个非常复杂的操作.需要占用非常长的时间,而WinFrom又不允许阻塞UI线程

后台线程

创建线程

 1   private void button2_Click(object sender, EventArgs e)
 2         {
 3             //创建一个委托指向其中一个方法
 4             ThreadStart threadStart = new ThreadStart(StartCaul);
 5             //创建线程
 6             Thread myThread = new Thread(threadStart);//可以直接放方法名进去 StartCaul
 7             //开启线程
 8             myThread.Start();
 9             //设置线程的优先级
10             myThread.Priority = ThreadPriority.Normal;//建议操作系统将创建的线程优先级设置为最高。
11             //可以给线程起个名字
12             myThread.Name = "myThreadBB";
13             //终止线程
14             myThread.Abort();
15             //阻塞主线程执行
16             myThread.Join(1000);
17             //设置后台线程
18             myThread.IsBackground = true;
19 
20         }
创建线程

控制线程结束

 1    bool isStop = false;
 2         private void StartCaul()
 3         {
 4             int a = 0;
 5             for (int i = 0; i < 600000000; i++)
 6             {
 7                 if (!isStop)
 8                 {
 9                     a = i;
10                 }
11                 else
12                 {
13                   
14                 }
15             }
16             //MessageBox.Show(a.ToString());
17             this.textBox1.Text = a.ToString();
18         }
控制线程结束

微软提供跨线程检测 不建议把他用一下方法取消

TextBox.CheckForIllegalCrossThreadCalls = false;

跨线程访问

 1  /// <summary>
 2         /// 完美的跨线程访问   要访问主线程创建的TextBox 需设置跨线程访问
 3         /// </summary>
 4         /// <param name="sender"></param>
 5         /// <param name="e"></param>
 6         private void button4_Click(object sender, EventArgs e)
 7         {
 8             //创建一个线程
 9             Thread thread1 = new Thread(ShowResult);
10             //设置为后台线程
11             thread1.IsBackground = true;
12             thread1.Start();
13         }
14         private void ShowResult()
15         {
16             int a = 0;
17             for (int i = 0; i < 600000000; i++)
18             {
19                
20                 a = i;
21               
22             }
23                  //现在就是对文本框进行跨线程访问 返回是true
24             if (this.textBox1.InvokeRequired)//是否要对文本框进行跨线程访问。
25             {
26                 //Invoke:去找创建TextBox的线程(主线程(UI线程)),由主线程完成委托方法的调用。
27                 //后面2个参数给方法传值
28                 //泛型约束<TextBox, string>
29                 this.textBox1.Invoke(new Action<TextBox, string>(ShowTextBoxValue), this.textBox1, a.ToString());//
30             }
31             else
32             {
33                 this.textBox1.Text = a.ToString();
34             }
35         }
36         //给文本框赋值函数 不需要返回值
37         private void ShowTextBoxValue(TextBox txt,string value)
38         {
39             txt.Text = value;
40 
41         }
完美的跨线程访问

线程执行带参数的方法

 1  private void button3_Click(object sender, EventArgs e)
 2         {
 3             //创建一个List集合
 4             List<int> list = new List<int>() {1,2,3,4,5 };
 5             //传一个方法
 6             ParameterizedThreadStart parThreadStart = new ParameterizedThreadStart(Show);
 7             Thread thread1 = new Thread(parThreadStart);
 8             //标记为后台线程
 9             thread1.IsBackground = true;
10             //Start方法有2个参数 向方法传递参数
11             thread1.Start(list);
12         }
13         private void Show(object obj)
14         {
15             //遍历list集合输出
16             List<int> list = obj as List<int>;
17             foreach (int i in list)
18             {
19                 MessageBox.Show(i.ToString());
20             }
21         }
线程执行带参数的方法

多线程同步

当多个线程访问同一资源时要加锁,多用户并发问题.加锁可以解决多线程访问同一资源问题,但是它带来的问题比较慢

 1      //开启2个线程调同一个方法 当多个线程访问同一资源时要加锁
 2 
 3         private void button5_Click(object sender, EventArgs e)
 4         {
 5           //  this.textBox1.Text = "safasdfd";
 6             Thread thread1 = new Thread(AddSum);
 7             thread1.IsBackground = true;
 8             thread1.Start();
 9 
10             Thread thread2 = new Thread(AddSum);
11             thread2.IsBackground = true;
12             thread2.Start();
13         }
14         //
15         private static readonly object obj = new object();
16 
17         private void AddSum()
18         {
19             lock (obj)  
20             {
21 
22                 for (int i = 0; i < 2000; i++)
23                 {
24                     int a = Convert.ToInt32(this.textBox1.Text);
25                     a++;
26                     this.textBox1.Text = a.ToString();
27                 }
28             }
29            
30         }
View Code

浏览器对服务器发送请求,等于开启了一个线程,线程本身是消耗资源的,一台web服务器挺不住太多线程,CPU来回切换消耗资源

lock 是一个语法糖  实际写法Monitor.Enter(obj)

线程池

 1 什么时候用线程池? 什么时候手动创建线程?
 2 1,能用线程池的就用线程池
 3 
 4 2.我们想手动关闭线程的话那么必须手动创建  Abort() Join()
 5 
 6 3.我们需要对线程池的线程的优先级做设置的情景下,只能使用手动创建线程
 7 
 8 4.如果执行的线程执行时间特别长,建议手动创建线程.
 9 
10 线程池:提高了线程的利用率,非常适合工作任务比较小,而且又需要使用单独的线程来解决的问题.
11 
12 线程切换消耗资源,cpu在切换线程的时候,需要把当前线程执行的状态保持到寄存器里面去.
13 
14 线程创建非常消耗资源.线程创建非常慢,占用大量的内存空间,每个线程最少1M内存开销.
线程池介绍
 1   Stopwatch  sw =new Stopwatch();
 2             sw.Start();
 3             for (int i = 0; i < 1000; i++)
 4             {
 5                new Thread(() =>
 6                  {
 7                       int i2 = 1 + 1;
 8                      
 9                     }).Start();
10            }
11            sw.Stop();
12            Console.WriteLine(sw.Elapsed.TotalMilliseconds);
13 
14             //重新开始计时
15           sw.Reset();
16            sw.Restart();
17            for (int i = 0; i < 1000; i++)
18           {
19                //从线程池取出一个线程
20               ThreadPool.QueueUserWorkItem(new WaitCallback(PoolCallBack), "sssss"+i);
21                //ThreadPool.GetMaxThreads
22            }
23            sw.Stop();
24            Console.WriteLine(sw.Elapsed.TotalMilliseconds);
25 
26            Console.ReadKey();
27           
28         }
29         private static void PoolCallBack(object state)
30         {
31             int i = 1 + 1;
32 
33         }
手动开启线程与使用线程池时间比较
原文地址:https://www.cnblogs.com/ligtcho/p/6653813.html