当前位置:首页 > 建站教程 > 双鸭山彼庞访汽车维修投资有限公司
作者:宗海卓
来源:安康蚜佳薪科技股份有限公司
发布时间:2019-09-27

双鸭山彼庞访汽车维修投资有限公司_c#之多线程之为所欲为

一 什么是多线程

1、 什么是进程?一个 exe 运行一次就会产生一个进程,一个 exe 的多个进程之 间数据互相隔离。

2、 一个进程里至少有一个线程:主线程。我们平时写的控制台程序默认就是单线程的,代 码从上往下执行,一行执行完了再执行下一行;

3、 什么是多线程:一个人两件事情同时做效率高。同一时刻一 个人只能干一件事情,其实是在“快速频繁切换”,如果处理不当可能比不用多线程效率还低

?

?

二??Thread 对象

2.1 thread基础写法

public static void ThreadTest()
        {
            int a = 0;
            Thread thread1 = new Thread(m=> 
            {
                for (int i = 0; i < 20; i++)
                {
                    a = a + 1;
                    Console.WriteLine("线程1:"+ a);
                }

            });

            Thread thread2 = new Thread(m =>
            {
            for (int i = 0; i < 20; i++)
            {
                    a = a + 1;
                Console.WriteLine("线程2:"+ a);
                }

            });
            
            thread1.Start();
            thread2.Start();
            Console.ReadKey();
        }

这段代码输出结果如下:

可以看出两个子线程启动后是并行执行的,所以输出结果没有按照顺序来

?

2.2 设置线程的优先级

thread1.Priority=ThreadPriority。。。

2.3? t1.Join()当前线程等待 t1 线程执行结束,实例如下:

这段代码执行过后输出的结果就是正常的从1输出到了40

public static void ThreadTest()
        {
            int a = 0;
            Thread thread1 = new Thread(m=> 
            {
                for (int i = 0; i < 20; i++)
                {
                    a = a + 1;
                    Console.WriteLine("线程1:"+ a);
                }

            });

            Thread thread2 = new Thread(m =>
            {
                //等待thread1线程任务完成后在执行
                thread1.Join();
                for (int i = 0; i < 20; i++)
                {
                    a = a + 1;
                Console.WriteLine("线程2:"+ a);
                }

            });
            //可以将参数传入到子线程中
            thread1.Start(a);
            //thread1.Join(); 或者将Join放在这里
            thread2.Start(a);
            Console.ReadKey();

        }

?

2.4?Interrupt方法

Interrupt 用于提前唤醒一个在 Sleep 的线程,Sleep 方法会抛出 ThreadInterruptedException 异常 代码如下:?

代码输出到9的时候线程会休眠8秒钟,但是运行到主线程thread1.Interrupt()时,子线程会被唤醒,然后执行catch里面的Console.WriteLine("线程被唤醒");之后接着从10开始输出到2000。需要注意的是只有线程自身能让自身休眠

public static void ThreadTest2()
        {
            Thread thread1 = new Thread(() =>
            {
                for (int i = 0; i < 2000; i++)
                {
                    if (i==10)
                    {
                        //唤醒线程之后会引发ThreadInterruptedException类型的异常,所以需要try catch
                        try
                        {
                            //子线程休眠8秒钟
                            Thread.Sleep(8000);
                        }
                        catch (ThreadInterruptedException ex)
                        {
                            Console.WriteLine("线程被唤醒");
                        }
                    }
                    Console.WriteLine(i);
                }
            });
            thread1.Start();
            //提前唤醒在沉睡的子线程
            Thread.Sleep(3000);
            thread1.Interrupt();
            Console.ReadKey();
        }

  

三 线程池

3.1、线程池:因为每次创建线程、销毁线程都比较消耗 cpu 资源,因此可以通过线程池进行 优化。线程池是一组已经创建好的线程,随用随取,用完了不是销毁线程,然后放到线程池 中,供其他人用。

3.2、用线程池之后就无法对线程进行精细化的控制了(线程启停、优先级控制等)

3.3、ThreadPool 类的一个重要方法:

  static bool QueueUserWorkItem(WaitCallback callBack)

  static bool QueueUserWorkItem(WaitCallback callBack, object state)

3.4、除非要对线程进行精细化的控制,否则建议使用线程池,因为又简单、性能调优又更好。

//QueueUserWorkItem是一个静态方法不需要New
public static void ThreadPool()
{
    System.Threading.ThreadPool.QueueUserWorkItem(m=> 
    {
        for (int i = 0; i < 1000; i++)
        {
            i++;
            Console.WriteLine(i);
        }
    });
    Console.ReadKey();
}

  

四 TPL风格的异步方法

TPL(Task Parallel Library)是.Net 4.0 之后带来的新特性,更简洁,更方便。现在在.Net 平台下已经大面积使用。

注意方法中如果有 await,则方法必须标记为 async,不是所有方法都可以被轻松的标记 为 async。WinForm 中的事件处理方法都可以标记为 async、MVC 中的 Action 方法也可以标 记为 async、控制台的 Main 方法不能标记为 async。? TPL 的特点是:方法都以 XXXAsync 结尾,返回值类型是泛型的 Task。? TPL 让我们可以用线性的方式去编写异步程序,不再需要像 EAP 中那样搞一堆回调、逻 辑跳来跳去了。

/TPL风格返回的Task 泛型的数据
//await 关键字等待异步方法返回
public static async void Task()
{
    WebClient wc = new WebClient();
    string s= await wc.DownloadStringTaskAsync("http://www.baidu.com");
    Console.WriteLine(s);
    Console.ReadKey();
}
public static void Task2()
{
    WebClient wc = new WebClient();
    //若果不使用await关键字就得使用Task类型来接收数据
    Task s2 = wc.DownloadStringTaskAsync("http://www.baidu.com");
    Console.ReadKey();
}

  

TPL feng ge fan hui de Task lt T gt fan xing de shu ju await guan jian zi deng dai yi bu fang fa fan hui public static async void Task WebClient wc new WebClient string s await wc. DownloadStringTaskAsync" http: www. baidu. com" Console. WriteLine s Console. ReadKey public static void Task2 WebClient wc new WebClient ruo guo bu shi yong await guan jian zi jiu de shi yong Task lt string gt lei xing lai jie shou shu ju Task lt string gt s2 wc. DownloadStringTaskAsync" http: www. baidu. com" Console. ReadKey  

自己编写一个TPL风格的异步方法:

使用了async关键字就必须返回Task泛型数据类型的数据

public static Task StringAsync()
{
   return Task.Run(() =>
    {
        Thread.Sleep(5000);
        return "hehe";
    });
          
}
// GET: Home
public async Task Index()
{

    var s = await StringAsync();
    return View();
}

  

如果返回值就是一个立即可以随手可得的值,那么就用 Task.FromResult()? 如果是一个需要休息一会的任务(比如下载失败则过 5 秒钟后重试。主线程不休息,和 Thread.Sleep 不一样),那么就用 Task.Delay()。 3、Task.Factory.FromAsync()把 IAsyncResult 转换为 Task,这样 APM 风格的 api 也可以用 await 来调 用。 4、编写异步方法的简化写法。如果方法声明为 async,那么可以直接 return 具体的值,不再用创建 Task,由编译器创建 Task:

static async Task F1Async() 
{ 
     return 1;
 } 
 
static Task F2Async() 
{  
     return Task.FromResult(3); 
} 
 
static Task F3Async() 
{  
     return Task.Run(()=> {  
     return 1 + 3;  }); 
}

一定要让 async 的传染性(调用异步方法要用 await,用了 await 方法就要声明为 async,调 用我这个 async 方法的地方必须要 await……)不要轻易直接调用 Task 的 Wait、WaitAll 等方 法。等待一个用 await,而不是 task.Wait();等待多个用 await Task.WhenAll(),而不是 Task.WaitAll()

当前文章:http://www.yc56xx.com/bk5sfqxji/107313-581050-76583.html

发布时间:03:06:31

香港马现场开奖结果??www.8896kk.com??马会六肖免费资料大全??63309开奖直播??惠泽社群??12生肖开奖结果??大红鹰报码室??香港马会最快开奖直播??东方心经彩图??www.44400444.com??

  • 本文标签:
  • 泉州市酪卦鄙有限公司