精华内容
下载资源
问答
  • Unity协程函数

    2017-07-21 14:12:49
    启动协程函数和停止协程函数参数类型要相同,比如使用协程函数的名字启动协程时,也要使用协程函数的名字停止协程。(Note: Do not mix the two arguments. If a string is used as the argument in StartCoroutine,...

    启动协程函数和停止协程函数参数类型要相同,比如使用协程函数的名字启动协程时,也要使用协程函数的名字停止协程。(Note: Do not mix the two arguments. If a string is used as the argument in StartCoroutine, use the string in StopCoroutine. Similarly, use the IEnumerator in both StartCoroutine and StopCoroutine.)

    代码块

    public class Ie : MonoBehaviour 
    {
        private IEnumerator ie;
        private Coroutine coroutine;
        void Start () 
        {
            ie = MyIE("1");
            StartCoroutine(ie);//方式一
    
            coroutine= StartCoroutine(MyIE("2"));//方式二
        }
        void Update () 
        {
            if (Input.GetKeyDown(KeyCode.Space))
            {
                StopCoroutine(ie);//方式一
                StopCoroutine(coroutine);//方式二
                //StopCoroutine(MyIE());//错误方式
            }
        }
        IEnumerator MyIE(string str)
        {
            while (true)
            {
                yield return null;
                Debug.Log(str);
            }
        }
    }
    展开全文
  • Lua中的协同函数 一,协同函数的定义和...启动coroutine.create定义的函数 coroutine.resume(Co,20,30) b.用coroutine.wrap定义一个协同函数 Co1=coroutine.wrap(function () local c=a+b return c end ) –1.启动co

    Lua中的协同函数

    一,协同函数的定义和启动:
    –a.用coroutine.create创建一个协程
    Co= coroutine.create(function(a,b)
    local c =a+b
    return c
    end
    )
    –1.启动coroutine.create定义的函数
    coroutine.resume(Co,20,30)

    b.用coroutine.wrap定义一个协同函数
    Co1=coroutine.wrap(function (a,b)
    local c=a+b
    return c
    end
    )
    –1.启动coroutine.wrap()函数
    Co1(20,30)

    二,协同函数的暂停
    Co=coroutine.create(function(a,b)
    print a+b
    coroutine.yield()
    end
    )
    三,协程函数的返回值
    Co2=coroutine.create(function (c,e)
    local d=c+e
    return d
    end
    )
    res,res1=coroutine.resume(Co2,20,30)–res 是否启动成功,res1返回值1

    四,协同函数的状态
    coroutine.states(Co) --返回的是当前协同的运行状态。

    展开全文
  • 每个Go程序启动的时候只有一个对用户可见的协程,我们称之为主协程。一个协程可以开启更多其它新的协程。 在Go中,开启一个新的协程是非常简单,我们只需要在一个函数调用之前使用一个go关键字,即可让此函数调用...

    协程(goroutine)

    Go不支持创建系统线程,所以协程是一个Go程序内部唯一的并发实现方式。每个Go程序启动的时候只有一个对用户可见的协程,我们称之为主协程。一个协程可以开启更多其它新的协程。

    在Go中,开启一个新的协程是非常简单的,我们只需要在一个函数调用之前使用一个go关键字,即可让此函数调用运行在一个新的协程之中。当此函数调用退出后,这个新的协程也随之结束。(不管其本身是否执行结束)我们可以称此函数调用为一个协程调用(或者为此协程的启动调用)。一个协程调用的所有返回值(如果存在的话)必须被全部舍弃。

    并发同步(concurrency synchronization)

    不同的并发计算可能会共享一些资源,其中共享内存资源最为常见。在一个并发程序中,常常会发生下面的情形:

    • 在一个协程向一段内存写数据的时候,另一个协程从此内存段读数据,结果导致读出的数据完整性得不到保证
    • 在一个协程向一段内存写数据的时候,另一个计算也向此段内存写数据,结果导致被写入的数据的完整性得不到保证

    这些情形被称为数据竞争(data race)。并发编程的一大任务就是要调度不同协程,控制它们对资源的访问时段,以使数据竞争的情况不会发生。此任务常称为并发同步(或者数据同步)。Go支持几种并发同步技术。并发编程中的其它任务包括:

    • 决定需要开启多少协程
    • 决定何时开启、阻塞、解除阻塞和结束哪些协程
    • 决定如何在不同的协程中分担工作负载

    协程的状态

    一个活动中的协程可以处于两个状态:运行状态阻塞状态。一个协程可以在这两个状态之间切换。注意,一个处于睡眠中的(通过调用time.Sleep)或者在等待系统调用返回的协程被认为是处于运行状态,而不是阻塞状态。

    当一个新协程被创建的时候,它将自动进入运行状态,一个协程只能从运行状态而不能从阻塞状态退出。一个处于阻塞状态的协程不会自发结束阻塞状态,它必须被另外一个协程通过某种并发同步方法来被动的结束阻塞状态。

    如果一个运行中的程序当前所有的协程都处于阻塞状态,则这些协程将永远阻塞下去,程序将被视为死锁了。当一个程序死锁后,官方标准编译器的处理是让这个程序崩溃。

    协程的调度

    并非所有处于运行状态的协程都在执行。在任一时刻,只能最多有和逻辑CPU数目一样多的协程在同时执行。我们可以调用runtime.NumCPU函数来查询当前程序可利用的逻辑CPU数目

    标准编译器采纳了一种被称为M-P-G模型的算法来实现协程调度。其中,M表示系统线程,P表示逻辑处理器(并非上述的逻辑CPU),G表示协程。大多数的调度工作是通过逻辑处理器(P)来完成的。逻辑处理器像一个监工一样通过将不同的处于运行状态的协程(G)交给不同的系统线程(M)来执行。一个协程在同一时刻只能在一个系统线程中执行。一个执行中的协程运行片刻后将自发的脱离让出一个系统线程,从而使得其它处于等待子状态的协程得到执行机会

    在运行时刻,我们可以调用runtime.GOMAXPROCS(n)函数来获取和设置逻辑处理器的数量。当n<1时,则不会更改当前设置,自从Go1.5之后,默认初始逻辑处理器的数量和逻辑CPU的数量一致。默认设置在大多数情况下是最佳选择。但是对于某些文件操作十分频繁的程序,设置一个大于runtime.NumCPU()GOMAXPROCS值可能是有好处的。

    延迟函数调用(defferred function call)

    在Go中,一个函数调用可以跟在一个defer关键字后面,形成一个延迟函数调用。和协程调用类似,被延迟的函数调用的所有返回值必须全部被舍弃。

    当一个函数调用被延迟后,它不会立即被执行。它将被推入由当前协程维护的一个延迟调用堆栈。当一个函数调用(可能是也可能不是一个延迟调用)返回并进入它的退出阶段后,所有在此函数调用中已经被推入的延迟调用将被按照它们被推入堆栈的顺序逆序执行。当所有这些延迟调用执行完毕后,此函数调用也就真正退出了。

    下面这个例子展示了如何使用延迟调用函数

    package main
    
    import "fmt"
    
    func main() {
    	defer fmt.Println("The third line")
    	defer fmt.Println("The second line")
    	fmt.Println("The first line")
    }
    

    输出结果:

    The first line
    The second line
    The third line
    

    事实上,每个协程维护着两个调用堆栈

    • 一个是正常的函数调用堆栈。在此堆栈中,相邻的两个调用存在着调用关系。晚进入堆栈的调用被早进入堆栈的调用所调用。此堆栈中最早被推入的调用是对应协程的启动调用
    • 另一个堆栈是上面提到的延迟调用堆栈。处于延迟调用堆栈中的任意两个调用之间不存在调用关系

    一个延迟调用可以修改包含此延迟调用的最内层函数的返回值

    package mian
    
    import "fmt"
    
    func Triple(n int) (r int) {
    	defer func() {
    		r += n // 修改返回值
    	}
    	
    	return n + n
    }
    

    延迟函数调用的必要性和好处

    延迟调用对于恐慌/恢复特性是必要的。另外延迟函数调用可以帮助我们写出更整洁和更棒的代码。

    协程和延迟调用的实参的估值时刻

    一个协程调用或者延迟调用的实参是在此调用发生时被估值的。更具体的说:

    • 对于一个延迟函数调用,它的实参是在此调用被推入延迟调用堆栈的时候被估值的
    • 对于一个协程调用,它的实参是在此协程被创建的时候估值的

    一个匿名函数体内的表达式是在此函数被执行的时候才会被逐个估值的,不管此函数是被普通调用还是延迟/协程调用

    package mian
    
    import "fmt"
    
    func main() {
    	func() {
    		for i:=0;i<3;i++ {
    			defer fmt.Println("a:",i)
    		}
    	}()
    	fmt.Println()
    	func() {
    		for i:=0;i<3;i++ {
    			defer func() {
    				fmt.Println("b:",i)
    			}()
    		}
    	}()
    }
    

    打印结果:

    a:2
    a:1
    a:0
    
    b:=3
    b:=3
    b:=3
    

    恐慌(panic)和恢复(recover)

    Go不支持异常抛出和捕获,而是推荐使用返回值显示返回错误。不过,Go支持一套和异常抛出/捕获类似的机制。此机制称为恐慌/恢复(panic/recover)机制

    我们可以调用内置函数panic来产生一个恐慌以使当前协程进入恐慌状态。一个恐慌不会蔓延到其它协程。

    进入恐慌状态是另一种使当前函数调用开始返回的途径。一旦一个函数调用产生一个恐慌,此函数调用将立即进入它的退出阶段,在此函数调用中被推入堆栈的延迟调用将按照它们被推入的顺序逆序执行。

    通过在一个延迟函数调用之中调用内置函数recover,当前协程中的一个恐慌可以被消除,从而使得当前协程重新进入正常状态。

    一些致命性错误不属于恐慌

    对于官方标准编译器来说,很多致命性错误(比如堆栈溢出和内存不足)不能被恢复。它们一旦产生,程序将崩溃。

    展开全文
  • Kotlin中协程的使用

    2020-07-16 14:56:03
    协程如何确保主线程安全协程的挂起本质协程的创建以及取消协程的启动协程的结构化并发,取消协程协程中异常处理 官方介绍协程 协程定义 协程定义:kotlin官方封装的线程api 使用方便 同步方式写出异步代码 挂起函数...

    官方介绍协程

    协程定义

    协程定义:kotlin官方基于JVM的线程实现的一个并发任务处理框架,封装的线程api

    • 使用方便,不使用回调实现线程切换,使用同步方式写出异步代码
    • 所有的耗时任务保证一定放在后台执行
    • 挂起函数执行完毕之后,协程会把它切换到原先的线程的线程。

    协程的基本用法

    常规函数中一般都有:call and return,协程在此之外添加了suspend和resume.

    • suspend 用于暂停执行的当前协程,并保存所有的局部变量
    • resume 用于已暂停的协程中暂停出恢复

    supend(挂起函数)是什么,有什么意义

    suspend,对协程的挂起并没有实际作用,其实只是一个提醒,函数创建者对函数的调用者的提醒,提醒调用者我是需要耗时操作,需要用挂起的方式,在协程中使用.

    • 需要注意的是挂起函数只能在挂起函数或者协程作用域中使用,为什么挂起函数需要在协程作用域中使用?因为普通函数没有suspend和resume这两个特性,所以必须要在协程的作用中使用。

    意义:

    • 语法层面:作为一个标记和提醒。通过报错来提醒调用者和编译器,这是一个耗时函数,需要放在后台执行。

    • 编译器层面:辅助 Kotlin 编译器来把代码转换成 JVM 的字节码。

    怎么自定义suspend函数?

    • 什么时候定义?

    需要耗时操作的时候,需要定义,例如io耗时操作(请求网络);获取数据库数据;一些等待一会需要的操作;列表排除,json解析等;

    • 怎么写suspend函数

    给函数前加上suspend 关键字,把内容用withContext包起来

    suspend fun testSuspendfun(){
          withContext(Dispatchers.IO){
    
          }
      }
    

    协程如何确保主线程安全

    • Dispatchers.Main 调用程序在Android的主线程中
    • Dispatchers.IO 适合主线程之外的执行磁盘或者网络io操作,例如文件的读取与写入,任何的网络请求
    • Dispatcher.Default 适合主线程之外的,cpu的操作,例如json数据的解析,以及列表的排序,

    协程的挂起本质

    • 本质就是切线程,完成之后只不过可以自动切回来

    协程挂起就是切个线程,在挂起函数执行完毕之后,协程会自动的重新切回它原先的线程,也就是稍后会被切回来的线程切换。切回来就是resume,恢复功能是协程,所以suspend函数需要在另一个suspend函数或者协程中调用.

    • 什么是协程的「非阻塞式挂起」

    阻塞的方式写出了非阻塞的方式

    协程的创建以及取消

    //创建一个协程
    
    Val scope = CoroutineScope(Dispatchers.Main+Job())
    
    通过Job获取协程的生命周期
    
    scope.launch{
    }
    
    其他耗时请求,例如从数据库中获取数据
    
     scope.async {
     }
    

    在KTX库为某些生命周期提供自己的CoroutineScope,例如ViewModel中viewModelScope,Lifecycle有lifecycleScope

    协程的启动

    • launch 启动新协程而不将结果返回给调用方
    //创建之后,不管后续
    launch(){
    }
    
    • async 启动一个新协程,并通过deferred的await方法暂停函数
    //返回deferred 对象
    val deferred async{
    
    }
    deferred.await()
    

    协程的结构化并发,取消协程

    协程的结构化并发,可以让协程非常便于管理。例如在关闭activity中要取消协程。如果是在线程中,取消所有的线程比较复杂。

    • 取消父协程以及父里面的子协程
      val scope = CoroutineScope(Dispatchers.Main+ Job())
            scope.launch {
                val job = launch {
    
                   val job1 =  launch {
                       
                    }
                }
                job.cancel()
            }
            scope.cancel()
    
    • 取消子协程某一个

    每一个协程都会返回一个job对象,通过调用job的cancle,可以去取消单个的协程的。

    val scope = CoroutineScope(Dispatchers.Main+ Job())
            scope.launch {
                val job = launch {
    
                   val job1 =  launch {
                       
                    }
                }
                job.cancel()
            }
            scope.cancel()
    

    协程中异常处理

    • 在协程内部中捕获异常
    val scope = CoroutineScope(Dispatchers.Main+ Job())
            scope.launch {
                try {
                    
                }catch (e:Exception){
                }
            }
    
    展开全文
  • 开篇前言kotlin的协程在初学者看来是一个很神奇东西,居然能做到用同步代码块实现异步调用,其实深入了解你会发现kotlin协程本质上是通过函数式编程风格对Java线程池一种封装,这样会带来很多好处,首先是...
  • 先接上篇说一下协程,四种方式第一、二...注解:asyncio模块不在详细讲解了,因为有更好的运行协程的方式为什么复杂呢?1、async 可跟其他关键字:async 函数、async for、async with 等,这样写的话,会非常麻烦也...
  • 协程的工作流程

    2019-10-31 11:58:22
    如何启动协程呢,启动前必须先预激 3、send(接收数据) 4、close 结束协程: 2 流程中装饰器没有处理异常,如果中间抛出异常,那么协程将终止,如果想尝试重新激活协程,会抛出stopineration 异常, ...
  • 例程一 协程A里面调用了协程B和协程C,添加事件循环时只添加了协程A,则协程B和协程C的启动顺序是按照被协程A调用先后顺序执行: import asyncio import sys import time async def func_1(): #使用 await 关键字...
  • 协程

    2018-08-24 10:35:31
    协程不是进程或线程,其执行过程更类似于子例程,或者说不带返回值的函数调用。 协程优势:1.无需线程上下文切换的消耗 2.无需加锁,协程就是一种单线程模式,串行不用锁 3.高并发,高扩展性 4.协程能保留上次调用...
  • 但对于多核CPU,利用多进程+协程的方式,能充分利用CPU,获得极高的性能。协程也是实现并发编程的一种方式。协程协程:是单线程下的并发,又称微线程。英文名是Coroutine。它和线程一样可以调度,但是不同的是线程的...
  • 前言Unity中协程经常会用到,可能大家也听过启动协程带来额外开销成本大约是标准函数调用三倍,还会分配一些内存,将当前状态存储在内存中,直到下一次调用它,因此要谨慎使用。禁用组件无法使初始化协程...
  • 文章目录前言一、协程库实现-独立栈1....前面介绍了协程的基本概念和协程切换的常见方式以后,本文将介绍如何通过c语言实现自己的协程库,分为独立栈和共享栈两种实现,代码见git仓库。 一、协程库实现-独.
  • lua的协程

    2017-06-15 16:28:00
    resume和yield为两个重要的函数,resume启动协程并可以传入参数,第一次传给主函数,第二次作为yield的返回值。然后协程返回数据是通过yield的参数实现的,yield的参数就是resume的返回值 co = coroutine.create...
  • 如果希望能够从运行事件循环同步代码中调用它,则必须提供一个包装器,该包装器实际启动一个事件循环并运行协程,直到完成:def sync_low_level():loop = asyncio.get_event_loop()loop.run_until_complete(low_...
  • 协程 轻量级,通过goroutine实现协程使用方法:go + 函数名:启动一个协程执行函数体 package main import ( "fmt" "time" ) func testRoutine() { fmt.Println("this is one routine!!!") } func main() { ...
  • 调用协程函数时会创建一个协程对象,然后调用者使用协程的send()方法运行这个函数的代码。协程可以使用await关键字(并提供另一个协程)暂停执行。暂停时,这个协程的状态会保留,使得下一次被唤醒时可以从暂停的...
  • LUA协程

    2017-05-26 18:53:00
    co 为 所要启动的协程。 第一次调用resume时,参数是协程函数入口参数,协程函数调用coroutine.yield之后交出控制权 后面继续调用resume恢复该协程时,参数是作为上次调用coroutine.yield处返回值 ...
  • kotlin协程的挂起suspend

    2020-12-26 11:32:56
    协程上一篇中我们知道了下面知识点: 协程究竟是什么 协程到底好在哪里 协程具体怎么用 ... 相同点:它们都可以用来启动一个协程,返回都是Coroutine,我们这里不需要纠结具体是返回哪个类。...
  • 协程:解释协程-源码

    2021-02-22 04:27:23
    并行性:-每个函数都在单独后台线程中运行,这是成本选择 协程是穿线最佳方法 暂停功能可轻松处理连续概念 延续:-函数在停止地方继续工作 ** thera是五种线程类型: 1-IO:-用于数据库,API调用 2-MAIN:-...
  • 2、协程的取消及超时

    2020-12-26 00:16:33
    在一个长时间运行的应用中你可能需要更细粒度的控制你的后台协程,比如一个用户在页面中启动了一个协程然后很快又把它关闭了,此时协程的返回结果已经不需要了,那么就应该在页面关闭的时候把它给取消掉;launch函数...
  • 1. 协程的创建与启动 2. 协程的线程调度 3. 协程的挂起和恢复 4. 不同 resumeWith 的解析 5. 协程整体结构 一. 协程的挂起、恢复和调度的设计思想 被 suspend 修饰符修饰的函数在编译期间会被编译器做...
  • Unity 协程的使用简介

    2017-08-01 16:17:58
    猴子原创,欢迎转载。...原文地址: http://www.cocos2dev.com/?p=496Coroutine在Unity3D中叫做协程或协同程序,和多线程类似,也就是说开启协同程序就是开启一个... Coroutine相关函数:StartCoroutine:启动一个协程
  • 破解 Kotlin 协程(3) - 协程调度篇

    千次阅读 2019-06-13 09:22:28
    上一篇我们知道了协程启动的几种模式,也通过示例认识了 launch 启动协程的使用方法,本文将延续这些内容从调度的角度来进一步为大家揭示协程的奥义。 1. 协程上下文 调度器本质上就是一个协程上下文的实现,我们...
  • 聊一聊go的协程

    2020-05-18 16:38:46
    最近在学习go语言,学习到了协程,来记录下学习的心路历程 先来看下例子:打印5个hello和5个world ...go 启动协程的方式就是使用关键字 go,后面一般接一个函数或者匿名函数 执行上述代码发现什
  • 上一篇我们知道了协程启动的几种模式,也通过示例认识了 launch 启动协程的使用方法,本文将延续这些内容从调度的角度来进一步为大家揭示协程的奥义。 协程上下文 调度器本质上就是一个协程上下文的实现,我们...
  • 在书《Lua程序设计(第4版)》的协程一章,第273-274页,书上有个例子,让我困惑不已...函数coroutine.resume (co [, val1, ···])用来启动或再次启动一个协程,使其由挂起状态变成运行状态。 resume函数相当于在...
  • 上一章介绍了通过函数的方式启动的协程,这一章我们测试一下用函数启动的协程,代码如下: using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class ...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 191
精华内容 76
关键字:

启动协程的函数