C#异步编程(async and await)及异步方法同步调用

1、什么是异步?

异步操作通常用于执行完成时间可能较长的任务,如打开大文件、连接远程计算机或查询数据库=异步操作在主应用程序线程以外的线程中执行。应用程序调用方法异步执行某个操作时,应用程序可在异步方法执行其任务时继续执行。

2、同步与异步的区别

同步(Synchronous):在执行某个操作时,应用程序必须等待该操作执行完成后才能继续执行。
异步(Asynchronous):在执行某个操作时,应用程序可在异步操作执行时继续执行。实质:异步操作,启动了新的线程,主线程与方法线程并行执行。

3、异步和多线程的区别

我们已经知道, 异步和多线程并不是一个同等关系,异步是最终目的,多线程只是我们实现异步的一种手段。异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回而可以做其它的事情。实现异步可以采用多线程技术或则交给另外的进程来处理。

简单的说就是:异步线程是由线程池负责管理,而多线程,我们可以自己控制,当然在多线程中我们也可以使用线程池。

就拿网络扒虫而言,如果使用异步模式去实现,它使用线程池进行管理。异步操作执行时,会将操作丢给线程池中的某个工作线程来完成。当开始I/O操作的时候,异步会将工作线程还给线程池,这意味着获取网页的工作不会再占用任何CPU资源了。直到异步完成,即获取网页完毕,异步才会通过回调的方式通知线程池。可见,异步模式借助于线程池,极大地节约了CPU的资源。

注:DMA(Direct Memory Access)直接内存存取,顾名思义DMA功能就是让设备可以绕过处理器,直接由内存来读取资料。通过直接内存访问的数据交换几乎可以不损耗CPU的资源。在硬件中,硬盘、网卡、声卡、显卡等都有直接内存访问功能。异步编程模型就是让我们充分利用硬件的直接内存访问功能来释放CPU的压力。

两者的应用场景:

  • 计算密集型工作,采用多线程。
  • IO密集型工作,采用异步机制。

C#异步代码参考(async and await)

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

namespace AsyncAwaitDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("main start..");
            AsyncMethod();
            Thread.Sleep(1000);
            Console.WriteLine("main end..");

            Console.ReadLine();
        }

        static async void AsyncMethod()
        {
            Console.WriteLine("start async");
            var result = await MyMethod();
            Console.WriteLine("end async");
            //return 1;
        }

        static async Task<int> MyMethod()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("Async start:" + i.ToString() + "..");
                await Task.Delay(1000); //模拟耗时操作
            }
            return 0;
        }
    }
}

使用Wait()GetAwaiter().GetResult()方法实现异步方法同步执行

using System;
using System.Threading.Tasks;

namespace AsyncTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Async Test job:");

            Console.WriteLine("main start..");

            Console.WriteLine("MyMethod()异步方法同步执行:");

            MyMethod().Wait();//在main中等待async方法执行完成

            int i = MyMethod().GetAwaiter().GetResult();//用于在main中同步获取async方法的返回结果

            Console.WriteLine("i:" + i);

            Console.WriteLine("main end..");

            Console.ReadKey(true);
        }

        static async Task<int> MyMethod()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("Async start:" + i.ToString() + "..");
                await Task.Delay(1000); //模拟耗时操作
            }
            return 0;
        }
    }
}

C# 异步编程 异步委托调用同步方法

同步化操作:

由前后紧接的组件或函数调用组成。一个同步化调用会阻塞整个进程直到这一个操作完成。
在这里插入图片描述

异步化操作:

不会阻塞启动操作的调用线程。调用程序必须通过轮流检测、软件中的中断信号或只是明确地等待完成信号来发现调用的完成。
在这里插入图片描述

.NET 为异步操作提供两种设计模式:

  • 使用 IAsyncResult 对象的异步操作。
  • 使用事件的异步操作。

.NET的许多方面都支持异步编程功能,这些方面包括:

  • 文件 IO、流 IO、套接字 IO。
  • 网络。
  • 远程处理信道(HTTP、TCP)和代理。
  • 使用 ASP.NET 创建的 XML Web services
  • ASP.NET Web 窗体。
  • 使用 MessageQueue 类的消息队列。

异步委托提供以异步方式调用同步方法的能力。

  • 当同步调用一个委托时,调用方法直接对当前线程调用目标方法。如果编译器支持异步委托,则它将生成该调用方法以及BeginInvokeEndInvoke 方法。
  • 如果调用BeginInvoke方法,则公共语言运行库将对请求进行排队并立即返回到调用方。将对来自线程池的线程调用该目标方法。提交请求的原始线程自由地继续与目标方法并行执行,该目标方法是对线程池线程运行的
  • 在回调中,使用EndInvoke 方法来获取返回值和输入/输出参数。如果没有对BeginInvoke指定回调,则可以在提交请求的原始线程上使用EndInvoke
using System;
using System.Threading;
using System.Runtime.Remoting.Messaging;

namespace ClassMain
{
    //委托声明(函数签名)
     delegate string MyMethodDelegate();

    class MyClass
    {
        //要调用的动态方法
        public string MyMethod1()
        {
            return "Hello Word1";
        }

        //要调用的静态方法
        public static string MyMethod2()
        {
            return "Hello Word2";
        }
    }
    class Class1
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            MyClass myClass = new MyClass();

            //方式1:  声明委托,调用MyMethod1
            MyMethodDelegate d = new MyMethodDelegate(myClass.MyMethod1);
            string strEnd = d();
            Console.WriteLine(strEnd);

            //方式2:  声明委托,调用MyMethod2 (使用AsyncResult对象调用)
            d = new MyMethodDelegate(MyClass.MyMethod2); //定义一个委托可以供多个方法使用      
            AsyncResult myResult;   //此类封闭异步委托异步调用的结果,通过AsyncResult得到结果.
            myResult = (AsyncResult)d.BeginInvoke(null, null);        //开始调用

            while (!myResult.IsCompleted)  //判断线程是否执行完成
            {
                Console.WriteLine("正在异步执行MyMethod2 .....");
            }
            Console.WriteLine("方法MyMethod2执行完成!");
            strEnd = d.EndInvoke(myResult);      //等待委托调用的方法完成,并返回结果  
            Console.WriteLine(strEnd);
            Console.Read();
        }
    }
}
  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的django视图函数,它基于用户的书单推荐可能喜欢的书籍: ```python from django.shortcuts import render from .models import Book, UserBook def recommended_books(request): # 获取当前用户的书单 user_books = UserBook.objects.filter(user=request.user).values_list('book_id', flat=True) # 获取其他用户也阅读过的书籍 other_users_books = UserBook.objects.exclude(user=request.user).values_list('book_id', flat=True) # 从其他用户的书单中获取与当前用户共同阅读的书籍 common_books = Book.objects.filter(id__in=user_books, id__in=other_users_books) # 对共同阅读的书籍按照出现频率进行排序 recommended_books = common_books.annotate(num_users=Count('userbook')).order_by('-num_users') return render(request, 'recommended_books.html', {'books': recommended_books}) ``` 这个视图函数做了以下几件事情: 1. 获取当前用户的书单。 2. 获取其他用户也阅读过的书籍。 3. 从其他用户的书单中获取与当前用户共同阅读的书籍。 4. 对共同阅读的书籍按照出现频率进行排序。 5. 将推荐的书籍传递给模板渲染。 视图函数中使用了两个模型:`Book`和`UserBook`。 `Book`模型表示一本书,有以下字段: ```python class Book(models.Model): title = models.CharField(max_length=200) author = models.CharField(max_length=200) description = models.TextField() ``` `UserBook`模型表示一个用户阅读了一本书,有以下字段: ```python class UserBook(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) book = models.ForeignKey(Book, on_delete=models.CASCADE) ``` `UserBook`模型中的`user`字段是一个外键,指向`User`模型,表示这个书籍是哪个用户阅读的。`book`字段是一个外键,指向`Book`模型,表示这个用户阅读了哪本书。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值