C#多线程和异步

在讲线程的时候,首先说一下进程,在计算机中可以认为一个程序就是一个进程。每个进程中又有多个线程。cpu在处理多线程任务时,并不是同时处理,也是随机的进行处理,只不过可以交替处理多个线程的任务,但由于CPU的速度很快,造成同时处理的假象。
线程(Thread):是进程中的基本执行单元,是操作系统分配CPU时间的基本单位 ,在进程入口执行的第一个线程被视为这个进程的 主线程 。可以分为前台线程和后台线程。只有当前台线程全部结束时,程序才可以退出。

多线程能实现的基础:

1、CPU运行速度太快,硬件处理速度跟不上,所以操作系统进行分时间片管理。这样,宏观角度来说是多线程并发 ,看起来是同一时刻执行了不同的操作。但是从微观角度来讲,同一时刻只能有一个线程在处理。

2、目前电脑都是多核多CPU的,一个CPU在同一时刻只能运行一个线程,但是 多个CPU在同一时刻就可以运行多个线程 。

多线程的优点:

可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。

多线程的不利方面:

线程也是程序,所以线程需要占用内存,线程越多占用内存也越多
多线程需要协调和管理,所以需要CPU时间跟踪线程
线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题
线程太多会导致控制太复杂,最终可能造成很多Bug
C#中线程的基本使用可以如下:

Thread thread1 = new Thread(new ParameterizedThreadStart(test.Func1));
thread1.Start("有参的实例方法");

Thread thread2 = new Thread(new ThreadStart(test.Func1));
thread2.IsBackground=true;
thread2.Start();

thread1是有参的使用方法,thread2是无参的使用方法。

线程同步

当我们使用线程的时候,效率最高的方式当然是异步,即各个线程同时运行,其间不相互依赖和等待。但当不同的线程都需要访问某个资源的时候,就需要同步机制了,也就是说当对同一个资源进行读写的时候,我们要使该资源在同一时刻只能被一个线程操作,以确保每个操作都是有效即时的,也即保证其操作的原子性。lock是C#中最常用的同步方式,格式为lock(objectA){codeB} 。

lock(objectA){codeB} 看似简单,实际上有三个意思,这对于适当地使用它至关重要:

  1. objectA被lock了吗?没有则由我来lock,否则一直等待,直至objectA被释放。
  2. lock以后在执行codeB的期间其他线程不能调用codeB,也不能使用objectA。
  3. 执行完codeB之后释放objectA,并且codeB可以被其他线程访问。
private static readonly object SequenceLock = new object();

public string XMethod(string params)
{
    // ...
    lock (SequenceLock)
    {
    //互斥内容
    //...
    }
}

跨线程访问

一般UI界面的控件都是主线程创建的,为了能够跨线程访问控件就需要用到委托,Action<Type,Type>是不带返回值 的委托Function<Type,Type>是带返回值的委托。通常与匿名委托连用。

public Form1()
        {
            InitializeComponent();
        }
        //点击按钮开启一个新线程
        private void myBtn_Click(object sender, EventArgs e)
        {
            Thread thread1 = new Thread(SetValues);
            thread1.IsBackground = true;
            thread1.Start();
        }

        //新线程给文本框赋值
        private void SetValues()
        {
            Action<int> setVal = (i) => { this.myTxtBox.Text = i.ToString(); };
            for (int i = 0; i < 10000; i++)
            {
                this.myTxtBox.Invoke(setVal, i);
            }
        }

Invoke:在”拥有控件的基础窗口句柄的线程“,即在本例的主线程上执行委托,这样就不存在跨线程访问了。

利用异步委托去创建线程

BeginInvoke方法触发你的异步方法,它和你想要执行的异步方法有相同的参数。另外还有两个可选参数,第一个是AsyncCallback委托是异步完成的回调方法。第二个是用户自定义对象,该对象将传递到回调方法中。BeginInvoke立即返回并且不等待完成异步的调用(继续执行该下面的代码,不需要等待)。BeginInvoke返回IAsyncResult接口,可用于检测异步调用的过程。

通过EndInvoke方法检测异步调用的结果。如果异步调用尚未完成,EndInvoke将阻塞调用线程,直到它完成。EndInvoke参数包括out和ref参数。
详情请点击C#中的BeginInvoke和EndInvoke

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值