• 异步多线程


    通过轮询方式,使用IsCompleted属性判断异步操作是否完成,这样在异步操作未完成前就可以让主线程执行另外的工作。代码如下:


    class Program
        {
            delegate string MyDelegate(string name);
    
            static void Main(string[] args)
            {
                ThreadMessage("Main Thread");
    
                //建立委托
    
                MyDelegate myDelegate = new MyDelegate(Hello);
    
                //异步调用委托,获取计算结果
    
                IAsyncResult result = myDelegate.BeginInvoke("Leslie", null, null);
    
                //在异步线程未完成前执行其他工作
    
                while (!result.IsCompleted)
    
                {
                    Thread.Sleep(200);      //虚拟操作
    
                    Console.WriteLine("Main thead do work!");
                }
    
                //下列 AsyncWaitHandle.WaitOne(int timeout) 可达到相同效果
    
                //while (!result.AsyncWaitHandle.WaitOne(200))
    
                //{
    
                //    Console.WriteLine("Main thead do work!");
    
                //}
    
     
    
                //此处可加入多个检测对象, while (!result.IsCompleted) ,while (!result2.IsCompleted)...也可以判断多个
    
                //WaitHandle[] waitHandleList = new WaitHandle[] { result.AsyncWaitHandle,........ };
    
                //WaitHandle[] waitHandleList = new WaitHandle[] { result.AsyncWaitHandle};
    
                //while (!WaitHandle.WaitAll(waitHandleList,200))
    
                //{
    
                //    Console.WriteLine("Main thead do work!");
    
                //}
    
    string data = myDelegate.EndInvoke(result); Console.WriteLine(data); Console.ReadKey(); } static string Hello(string name) { ThreadMessage("Async Thread"); Thread.Sleep(2000); return "Hello " + name; } static void ThreadMessage(string data) { string message = string.Format("{0}\n ThreadId is:{1}", data, Thread.CurrentThread.ManagedThreadId); Console.WriteLine(message); } }

    上诉情况好比,硬件中的 总线 被占用的情况,如果外设需要请求总线,那么需要不断的询问 是否别人使用完毕,或者我是否可以申请了。

    这种方式,现实中比较贴切,但是对于追求高效率的硬件设备,过于频繁的请求可不是特别的好。使用轮询方式来检测异步方法的状态

    非常麻烦,而且效率不高,有见及此,.NET为 IAsyncResult BeginInvoke(AsyncCallback , object)准备了一个回调函数。使用

    AsyncCallback 就可以绑定一个方法作为回调函数,回调函数必须是带参数 IAsyncResult 且无返回值的方法:

    void AsycnCallbackMethod(IAsyncResult result) 。在BeginInvoke方法完成后,系统就会调用AsyncCallback所绑定的回调函数

    ,最后回调函数中调用 XXX EndInvoke(IAsyncResult result) 就可以结束异步方法,它的返回值类型与委托的返回值一致。

    如下代码:利用回调函数实现异步多线程调用,也是在现实中比较实用的


    class Program
    {
    public class Person
    {
    public string Name;
    public int Age;
    }
    
    delegate string MyDelegate(string name);
    
    static void Main(string[] args)
    {
    ThreadMessage("主线程开始!");
    
    //建立委托
    MyDelegate myDelegate = new MyDelegate(Hello);
    
    //建立Person对象
    Person person = new Person();
    person.Name = "Elva";
    person.Age = 27;
    
    //异步调用委托,输入参数对象person, 获取计算结果
    myDelegate.BeginInvoke("Leslie", new AsyncCallback(Completed), person);
    
    //在启动异步线程后,主线程可以继续工作而不需要等待
    for (int n = 0; n < 6; n++)
    {
    Console.WriteLine(" 主线程运行!");
    Thread.Sleep(2000); //为了看到异步线程结束后主线程还在工作,sleep
    
    }
    Console.WriteLine(" 主线程运行!");
    Console.WriteLine("");
    Console.ReadKey();
    }
    
    static string Hello(string name)
    {
    ThreadMessage("异步线程运行!");
    Thread.Sleep(2000);
    return "\nHello " + name;
    }
    
    static void Completed(IAsyncResult result) //可以用该返回返回
    {
    ThreadMessage("异步线程完成");
    
    //获取委托对象,调用EndInvoke方法获取运行结果
    AsyncResult _result = (AsyncResult)result;
    MyDelegate myDelegate = (MyDelegate)_result.AsyncDelegate;
    string data = myDelegate.EndInvoke(_result);
    //获取Person对象
    Person person = (Person)result.AsyncState;
    string message = person.Name + "'s age is " + person.Age.ToString();
    Console.WriteLine(data + "\n" + message);
    }
    
    static void ThreadMessage(string data)
    {
    string message = string.Format("{0}\n 当前线程ID为:{1}",
    data, Thread.CurrentThread.ManagedThreadId);
    Console.WriteLine(message);
    }
    }

    主线在调用BeginInvoke方法可以继续执行其他命令,而无需再等待了,这无疑比使用轮询方式判断异步方法是否完成更有优势。
    在异步方法执行完成后将会调用AsyncCallback所绑定的回调函数,注意一点,回调函数依然是在异步线程中执行,这样就不会影响主线程的运行,
    这也使用回调函数最值得青昧的地方。
    在回调函数中有一个既定的参数IAsyncResult,把IAsyncResult强制转换为AsyncResult后,就可以通过 AsyncResult.AsyncDelegate 获取原委托,
    再使用EndInvoke方法获取计算结果。
  • 相关阅读:
    linux内核之情景分析mmap操作
    linux内核情景分析之匿名管道
    linux内核情景分析之命名管道
    linux内核情景分析之信号实现
    Linux内核情景分析之消息队列
    linux2.4内核调度
    聊聊程序的配置文件
    汽车引擎是怎么工作的
    Go对OO的选择
    为而不争
  • 原文地址:https://www.cnblogs.com/imyao/p/5316975.html
Copyright © 2020-2023  润新知