多线程

1.获取对当前线程的引用,只需要调用静态属性Thread.CurrentThread; Thread.GetDomain();//获取当前线程所在的应用程序域;Thread.CurrentContext;获取当前操作操作线程的上下文。


2.几乎无法控制底层系统和CLR对线程的调度。


3.原子性操作在多线程环境下总是线程安全的。通常的操作都不是原子操作,包括++i,赋值操作等。


4.通过Invoke方法调用委托,实际上是等待委托函数调用完成返回后,接着运行,这里并没有创建一个新的线程,而是同一个线程。(同步)

委托同步调用:

public delegate string TestDelegate(int a);
    public class MyClass
    {
        private void Func1()
        {
            TestDelegate test = new TestDelegate(Func2);
            string result = Func2(2);
            test.Invoke(3);  //两种同步调用
        }


        private string Func2(int a)
        {
            Thread.Sleep(3000);
            Thread t = Thread.CurrentThread;
            int id = t.ManagedThreadId;
            return (a.ToString() + id.ToString());
        }
    }


5.通过BeginInvoke调用委托(异步)

声明的委托编译器帮助生成了三个函数


异步调用:

public delegate string TestDelegate(int a);
    public class MyClass
    {
        private void Func1()
        {
            TestDelegate test = new TestDelegate(Func2);
            string result = Func2(2);
            test.Invoke(3);  //两种同步调用
            IAsyncResult iret = test.BeginInvoke(3, null, null);
            Console.WriteLine("主线程没有暂停而是继续执行!");
            result = test.EndInvoke(iret);

            Console.WriteLine("在这之前需要等待次线程执行返回!");
        }

        private string Func2(int a)
        {
            Thread.Sleep(3000);
            Thread t = Thread.CurrentThread;
            int id = t.ManagedThreadId;
            return (a.ToString() + id.ToString());
        }
    }

可以通过轮询判断IAsyncResult.IsCompleted 属性来获取次线程是否执行完成,但是这并高效;可以让次线程执行完成后主动通知主线程。

可以在BeginInvoke时候提供一个System.AsyncCallBack对象,当异步调用完成时,委托会调用这个指定的方法。

如下:

public delegate string TestDelegate(int a);
    public class MyClass
    {
        private bool isOk = false;
        private void Func1()
        {
            TestDelegate test = new TestDelegate(Func2);
            IAsyncResult iret = test.BeginInvoke(2, new AsyncCallback(Func3), "传入自定义参数");
            Console.WriteLine("主线程没有暂停而是继续执行!");
            string result = test.EndInvoke(iret);

            Console.WriteLine("在这之前需要等待次线程执行返回!");
            while (!isOk)
            { 
                
            }
            Console.WriteLine("the end");
        }
        private void Func3(IAsyncResult ar) //次线程在调用异步委托完成时将以同步方式调用该方法,这里的ar参数实际上就是由BeginInvoke返回值传入
        {
            Thread t = Thread.CurrentThread;
            Console.WriteLine(t.ManagedThreadId);
            AsyncResult ar_1 = (AsyncResult)ar;
            TestDelegate a = (TestDelegate)ar_1.AsyncDelegate;
            string str = (string)ar_1.AsyncState;
            string result = a.EndInvoke(ar_1);
            isOk = true;

        }
        private string Func2(int a)
        {
            Thread.Sleep(3000);
            Thread t = Thread.CurrentThread;
            int id = t.ManagedThreadId;
            return (a.ToString() + id.ToString());
        }
    }


6.使用Thread

System.Threading命名空间部分类型
Interlocked:为多个线程共享访问的类型提供原子操作。
Monitor    :使用锁定和等待信号来同步线程对象。C#lock关键字在后台使用的就是Monitor对象。
ParameterizedThreadStart:委托,它允许线程调用包含任意多个参数的方法
Thread     :代表CLR中执行的线程。使用这个类型,能够在初始的应用程序域中创建额外的线程。
ThreadPool:用于和一个进程中的(由CLR维护的)线程池交互。
Timer:提供指定时间间隔执行方法的机制
TimerCallback:该委托类型应与Timer类型一起使用

示例:

public class ThreadPara
    {
        public ThreadPara()
        { 
            this.Id = default(int);
            this.Name = "";
        }
        public ThreadPara(int id, string name)
        {
            this.Id = id;
            this.Name = name;
        }
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class MyClass1
    {
        private void Func1()
        {
            Thread t = new Thread(ThreadMethoed);  //无参线程入口参数
            t.IsBackground = true;
            t.Start();
            Thread t_1 = new Thread(new ThreadStart(ThreadMethoed));//另一种无参
            Thread t_2 = new Thread(new ParameterizedThreadStart(ThMethoedOnePara)); //有一个参数
            t_2.Start("aaaa");
            Thread t_3 = new Thread(new ParameterizedThreadStart(ThMethoedMorePara)); //多个参数
            ThreadPara thPara = new ThreadPara();
            t_3.Start(thPara);

        }
        private void ThMethoedMorePara(object obj)
        {
            ThreadPara para = (ThreadPara)obj;
            Console.WriteLine(para.Id + para.Name);
        }
        private void ThMethoedOnePara(object obj)
        {
            string str = (string)obj;
            Console.WriteLine(str);
        }
        private void ThreadMethoed()
        {
            Console.WriteLine("另一个线程");
        }
    }


7.使用AutoResetEvent类同步线程
在需要等待的线程中,创建该类的实例,向构造函数传入false,表示未收到通知,然后在需要等待的地方调用WaitOne()方法。
public class MyClass1
    {
        AutoResetEvent autoE = new AutoResetEvent(false);
        private void Func1()
        {
            Thread t = new Thread(ThreadMethoed);  //无参线程入口参数
            t.Start();
            Thread t_3 = new Thread(new ParameterizedThreadStart(ThMethoedMorePara)); //多个参数
            ThreadPara thPara = new ThreadPara(2, "aaaa");
            t_3.Start(thPara);
            autoE.Set();
        }
        private void ThMethoedMorePara(object obj)
        {
            autoE.WaitOne();
            ThreadPara para = (ThreadPara)obj;
            Console.WriteLine(para.Id + para.Name);
        }       
        private void ThreadMethoed()
        {
            autoE.WaitOne();
            Console.WriteLine("另一个线程");
        }
    }


8.前台线程和后台线程

前台线程:能阻止应用程序的终结,知道所有的前台线程都终结后,CLR才能关闭应用程序(即卸载承载的应用程序域)。
后台线程:被CLR认为是程序执行中可做出牺牲的途径,即在任何时候都可以被忽略。如果所有前台线程终止,当前应用程序域被卸载,所有后台线程也会被自动终止。


9.使用lock(首选)关键字,同步访问共享资源
该关键字允许定义一段线程同步的代码块。lock关键字需要定义一个标记(即一个对象的引用),线程在进入锁定范围的时候必须获得这个标记。通常定义一个私有的对象(object类型)作为锁标识。

public void FuncLock()
        {
            lock (obj)
            {
               
            }          
        }


10.使用System.Monitor同步

lock(obj)
{
}

等价为:
try
{    
      Monitor.Enter(obj) 
}
catch()
{}
finally
{
      Monitor.Exit(obj) 
}


11.System.Threading.Interlocked类型进行同步

部分静态成员

Decrement()  安全的减一

Exchange() 安全的交换

Increment() 安全的加一

示例:

 public int AddOne(ref int val)
        {
            int newVal = Interlocked.Increment(ref val);
            return newVal;
        }


12.使用特性[Synchronization]进行同步

这个类级别的特性有效的使对象的所有示例的成员都保持线程安全。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值