C#多线程Task注意事项

学习过程:C#多线程的写法有很多,网上都能搜到,各有优劣。作为新手,最讨厌网上那种类似“多线程的5种方式”之类的文章,我不可能5中方式都使用一遍,我只需要其中一种最合适的。
代老师推荐向我Task类。下面是我个人对它的理解:

1、编程效率高,但损失性能
Task是Thread的升级版,会更好用。编程方便,代码量少。Task会帮你管理线程,程序员只要把握好什么时候启动线程,其他不需要操心。什么时候关闭线程、线程是否是后台线程等都是系统自己处理。强大的功能,肯定会降低效率。大部分程序不用考虑这点微乎其微的性能损失。大型互联网项目,一般也不会使用C#去写。就像初学try{}catch{}的时候,也说它会降低性能,但是项目中,几乎每个方法都写了try{}catch{},用来记录报错Log,性能影响微乎其微,可以忽略不计。
下面是2中Task启动线程的常用写法:

//写法1:
Task.Run(TestShow/*无参方法名称*/);

//方法2:
Task.Run(() =>
{
	/*
	* 代码块
	*/
});

写法1,适用于调用单个无参方法;
写法2,适用于调用多行代码块;

2、线程启动有延迟
线程启动有几十毫秒时间延迟,并不是立即启动。下面是测试代码和结果:

using System;
using System.Diagnostics;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch sw1 = new Stopwatch();
            sw1.Start();
            Task.Run(() =>
            {
                Stopwatch sw2 = new Stopwatch();
                sw2.Start();
                //线程代码主体
                sw2.Stop();
                Console.WriteLine("执行线程耗时:" + sw2.ElapsedMilliseconds);
            });
            sw1.Stop();
            Console.WriteLine("Task启动耗时:" + sw1.ElapsedMilliseconds);
            Console.ReadKey();
        }
    }
}

线程启动有延迟

执行代码的耗时,取决于代码块的内容。但是启动线程需要花27ms(这个时间不是固定的,跟设备、时机等多种因素相关。)

3、线程启动顺序随机
主线程按顺序写了9 个线程,代码执行的过程是按顺序执行了线程启动的9行代码。惯性思维,线程是顺序启动的。实际情况却不是,线程启动的顺序随机,下面是测试代码和结果:

using System;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 9; i++)
            {
                Task.Run(TestShow);
            }
            Console.ReadKey();
        }
        static int k = 0;
        private static void TestShow()
        {
            k++;
            Console.WriteLine("线程:" + k);
        }
    }
}

线程启动随机这点很重要,有个项目,我想记录与PLC通讯的所有信息记录下来,又不想损耗PLC的读写效率,想到使用的Task多线程执行记录的信息,然而时间不是按顺序的记录的,查找问题异常困难,当场裂开。然后,代老师告诉我,Task的执行顺序是随机的,如果对顺序有要求,可以使用队列。

4、数据不安全
看上述范例,按照设想应该出现1~9的随机数,但是却少了一个1,多了一个3。具体怎么解决,我还没查到,代老师在居家隔离,并且在开会,他告诉我使用Interlocked,但我查了网上资料,没搞出来,下次再说。上述范例比较极端,正常人也不会让同一个任务同时被多个线程调用。

5、不用手动结束线程
多线程有2个结束方式:
a、线程代码运行结束,线程自动结束并自动销毁;
b、手动中止并销毁;
写代码时,尽可能避免手动中止。没有死循环的代码,会按照方式a的操作,执行完成后结束线程。如果在线程中出现了while等死循环,尽量用变量控制它自然结束,按照方式a的操作,执行完成后结束线程。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C#气氛组队员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值