c#基础学习 - 线程,任务与同步

使用线程的几个原因, 假设从应用程序中进行网络调用需要一定时间,用户不希望分割用户界面,并长期等待,希望同时执行其他一些操作,或者取消发送给服务器的请求。这些可以用线程实现。

对于所有需要等待的操作,如文件,数据库或者网络访问带来的等待,可以启动一个新线程,同时完成其他任务。一个进程的多个线程可以同时运行与不同CPU,或者多核CPU的不同内核。 如果线程访问相同数据,必须实现同步机制,否则极易出错。

运行在服务器上的应用程序,带带客户请求的线程,成为侦听器线程,只要接收到请求,就把他传给另一个工作线程,之后继续与客户通讯。侦听器会立即返回,接收下一个客户发送的下一个请求。

进程包含资源: window句柄,文件系统句柄或其他内核对象。每个进程都分配了虚拟内存,一个进程至少包含一个线程,操作系统会调度线程,线程有一个优先级,正在处理的程序的位置计数器,一个存储局部变量的栈。 每个线程都有自己的栈,但程序代码的内存和堆有一个进程的所有线程共享,因为寻址都是在内存中完成,这使得线程间通讯非常的快。 

1. 异步委托: 创建线程的一个简单的方法是定义委托, 并异步调用它,委托是方法的类型安全的引用,Delegate类还支持异步调用方法,在后台,委托类Delegate会创建一个执行任务的线程;委托使用线程池来完成异步操作。测试一下委托的异步特性, 从一个需要时间完成的方法测试,TasksAWhile()方法需要经过第2个变量

    class Program
    {
        static void Main(string[] args)
        {
            //TakesAWhile(1, 10000);
            TakesAWhileDelegate d1 = TakesAWhile; // 使用委托调用一次这个方法
            d1(2, 1000);
            Console.ReadKey();
        }
        public delegate int TakesAWhileDelegate(int data, int ms);
        static int TakesAWhile(int data, int ms)
        {
            Console.WriteLine("TakesAWhile started");
            Thread.Sleep(ms);
            Console.WriteLine("TakesAWhile completed");
            return ++data;
        }
    }
接下来如果后台执行这个委托的操作,在10秒的漫长等待中,在屏幕上打印"."应该如何操作呢? 使用"投票"技术,通过IAsyncResult检验委托是否完成了。 而开始调用委托,这是用委托的方法: BeginInvoke(),而BeginInvoke返回类型就是IAsyncResult,而BeginInvoke总是包含两个参数(object, AsyncCallback),  IAsyncResult类型的返回对象,包含一个属性"IsCompleted", 用来判断委托是否完成任务;  只要委托没有完成,主线程就继续执行while循环。接下来程序改为:

        static void Main(string[] args)
        {
            //TakesAWhile(1, 3000);
            TakesAWhileDelegate d1 = TakesAWhile;
            //开始调用委托:
            IAsyncResult ar = d1.BeginInvoke(1, 10000, null, null);
            while (!ar.IsCompleted)
            {
                Console.Write(".");
                Thread.Sleep(50); //每次打点等待0.05秒
            }
            int result = d1.EndInvoke(ar); // 结束调用时要输入IAsyncResult类型的参数
            Console.WriteLine("Result: {0}", result);
        }
以上是通过委托线程调用方法的基本例子,可以看到主线程和委托线程同时运行,在委托线程执行完毕后,主线程就停止循环。
处理等到线程完全结束,还可以通过等待句柄来判断是否结束,如果不用ar.IsCompleted, 主线程的循环会一直继续,如果设置循环一直跑下去,即使后台线程结束,主线程也不会结束。这是就需要ar.AsyncWaitHandle.WaitOne(time, false)来进行干预:

       static void Main(string[] args)
        {
            //TakesAWhile(1, 3000);
            TakesAWhileDelegate d1 = TakesAWhile;
            //开始调用委托:
            IAsyncResult ar = d1.BeginInvoke(1, 10000, null, null);
            //while (!ar.IsCompleted)
            while(true)
            {
                Console.Write(".");
                if (ar.AsyncWaitHandle.WaitOne(50, true)) //50表示异步执行的时间间隔,true表示在等待之前是否退出同步域;
                {
                    Console.Write(".");
                    //Thread.Sleep(50); //每次打点等待0.05秒
                    break;
                }
            }
            int result = d1.EndInvoke(ar); // 结束调用时要输入IAsyncResult类型的参数
            Console.WriteLine("Result: {0}", result);
            Console.ReadKey();
        }
接下来看看回调方法的作用,作为等待结果的第三种方法,定义回调函数,并且在BeginInvok()方法的第三个参数中,可以传递一个满足AsyncCallback委托的需求方法
        static void Main(string[] args)
        {
            TakesAWhileDelegate d1 = TakesAWhile;
            d1.BeginInvoke(1,3000, TakesAWhereCompleted, d1);
            for (int i = 0; i < 100; i++)
            {
                Console.Write("+");
                Thread.Sleep(50);
            }
        }

        static void TakesAWhereCompleted(IAsyncResult ar)
        {
            if (ar == null) throw new ArgumentNullException("ar");
            TakesAWhileDelegate d1 = ar.AsyncState as TakesAWhileDelegate;
            Trace.Assert(d1!=null, "Invalid object type");

            int result = d1.EndInvoke(ar);
            Console.WriteLine("result: {0}",result);
        }
        public delegate int TakesAWhileDelegate(int data, int ms);
        static int TakesAWhile(int data, int ms)
        {
            Console.WriteLine("TakesAWhile started");
            Thread.Sleep(ms);
            Console.WriteLine("TakesAWhile completed");
            return ++data;
        }



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值