U3d 使用 异步 async await

  U3d 使用 异步 async await




   1.1 下载 CSharp60Support 文件夹,里面包含需要的文件
                百度网盘:  https://pan.baidu.com/s/1kVJfy6b 密码: 3pzf
    2. 复制 CSharp60Support 这个文件夹到Unity项目。它应该放在项目的根目录(重要理解,不要放在Assets下) , Assets文件夹同级目录

    3. 导入 CSharp60Support for Unity 5.unitypackage 到你的项目。这是位于 csharp60support 文件夹内

    4. 在 u3d 里 选中 CSharp 6.0 Support 文件夹 右键 Reimport All

演示 



using UnityEngine;
using System.Threading.Tasks;
//无返回值情况
class Program : MonoBehaviour
{
    void Start()
    {
        ExecuteAsync(); //新建一个线程执行这个函数,不阻塞主线程,立即执行下面
        Debug .Log( "start" );
    }
     async void ExecuteAsync()
    {
        await TaskEx .Run(() =>
        {
            Debug .Log( "Async Executed" );
        });
        Debug .Log( "End" );
    }
}

输出结果:
      Debug .Log( "start" );
Debug .Log( "Async Executed" );
Debug .Log( "End" );


using UnityEngine;
using System.Threading.Tasks;
//有返回参数阻塞式
class Program1 : MonoBehaviour
{
    void Start()
    {
        var t = ExecuteAsync(); //新建一个线程执行这个函数
        t.Wait(); //阻塞,一直等待函数执行完成
        Debug .Log( "start" );
         string result =t.Result; //返回值
    }
    async Task < string > ExecuteAsync()
    {
        await TaskEx .Run(() =>
        {
            Debug .Log( "Async Executed" );
        });
        Debug .Log( "End" );
        return "return Executed" ;
    }
}

输出结果:
Debug .Log( "Async Executed" );
Debug .Log( "End" );
Debug .Log( "start" );




using UnityEngine;
using System.Threading.Tasks;
public class Testt2 : MonoBehaviour
{
        void Start ()
       {
        YhyTools .LogTime( "Test2 start join" );
        var t = ShowRandomImages();
           t.Wait();
           string result =t.Result; //返回值
        YhyTools .LogTime( "Test2 start end" );
       }
    private async Task < string > ShowRandomImages()
    {
        for ( int i = 0; i < 9; i++)
        {
            await TaskEx .Delay(1000); //延迟一秒
            YhyTools .LogTime( "ShowRandomImages" );
        }
        return "1" ;
    }
}
输出结果:
                    


主要的类 Task  TaskEx  AsyncTools
await  0;  //等待指定的秒数,如果参数是负数或者0 等一帧。参数可以是 int float
await TaskEx .Delay(100);//开始一个任务,指定时间后完成
await AsyncTools .ToThreadPool();//切换到后台线程的执行。
await AsyncTools .ToLateUpdate();//切换主线程的更新上下文的执行。
          .ToFixedUpdate();
          . ToUpdate();



下面是官网例子

using System;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
public class CrossPlatformTest : MonoBehaviour
{
        private void Start()
       {
               Type type = null ;
               foreach ( var assembly in AppDomain .CurrentDomain.GetAssemblies())
              {
                     type = assembly.GetType( "System.Threading.Platform" );
                      if (type != null )
                     {
                            break ;
                     }
              }
               var methodInfo = type.GetMethod( "Yield" , BindingFlags .Static | BindingFlags .NonPublic);
              ShowResult( false );
              methodInfo.Invoke( null , null );
              ShowResult( true );
       }
        private static void ShowResult( bool success)
       {
               Camera .main.backgroundColor = success ? Color .green : Color .magenta;
               var textObject = FindObjectOfType< Text >();
              textObject.text = success ? "SUCCESS" : "FAIL" ;
       }
}

#if UNITY_5
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
public class AsyncOperationAwaiterTest : MonoBehaviour , IPointerClickHandler
{
        private Texture originalTexture;
        private Texture2D texture;
        private Material material;
        public async void OnPointerClick( PointerEventData eventData)
       {
               Debug .Log( "downloading..." );
               var request = UnityWebRequest .Get( "http://placeimg.com/512/512" );
               await request.Send();
               Debug .Log( "downloaded " + request.downloadedBytes + " bytes" );
              texture.LoadImage(request.downloadHandler.data, true );
              material.mainTexture = texture;
       }
        private void Start()
       {
              material = GetComponent< Renderer >().sharedMaterial;
              originalTexture = material.mainTexture;
              texture = new Texture2D (512, 512);
               Debug .Log( " \n --> Click on the box to change its texture <-- \n " );
       }
        private void OnDestroy()
       {
              Destroy(texture);
              material.mainTexture = originalTexture;
       }
        private void Update()
       {
              transform.Rotate(0, 90 * Time .deltaTime, 0);
       }
}
#endif

using UnityEngine;
using UnityEngine.UI;
internal class Logger : MonoBehaviour
{
    private Text textControl;
    private void Awake()
    {
        textControl = GetComponent< Text >();
#if UNITY_5
        Application .logMessageReceivedThreaded += Application_logMessageReceived;
#else
        Application.RegisterLogCallback(Application_logMessageReceived);
#endif
        Debug .Log( "<color=red>Current platform: " + Application .platform + "</color> \n " );
    }
    private void Application_logMessageReceived( string message, string stackTrace, LogType type)
    {
        textControl.text += message + " \n " ;
    }
}

using System;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using Random = UnityEngine. Random ;
public class SlideshowDemo : MonoBehaviour
{
        public RawImage rawImage;
        public Text counterText;
        public Button startButton;
        public Button abortButton;
       [ Range (.1f, 5)]
        public float delayInSeconds = 1;
        private Texture2D texture;
        private CancellationTokenSource tokenSource;
        private void Start()
       {
              texture = new Texture2D (320, 200);
              rawImage.texture = texture;
       }
        private void Destroy()
       {
              Destroy(texture);
       }
        public async void StartSlideshow() // async methods can be on-click handlers, coroutines can't
       {
              tokenSource = new CancellationTokenSource ();
              startButton.interactable = false ;
              abortButton.interactable = true ;
               try
              {
                      Debug .Log( "Slideshow started" );
                      await ShowRandomImages( Random .Range(2, 21), tokenSource.Token);
                      Debug .Log( "Run to completion" );
              }
               catch ( TaskCanceledException )
              {
                      Debug .Log( "Aborted" );
              }
               finally
              {
                     startButton.interactable = true ;
                     abortButton.interactable = false ;
              }
       }
        public void AbortSlideshow()
       {
              abortButton.interactable = false ;
              tokenSource.Cancel();
       }
        private async Task ShowRandomImages( int count, CancellationToken cancellationToken)
       {
               for ( int i = 0; i < count; i++)
              {
                      var image = await AsyncTools .DownloadAsBytesAsync( "http://placeimg.com/320/200" , cancellationToken);
                     texture.LoadImage(image);
                     rawImage.SetNativeSize();
                     counterText.text = $" {i + 1} of {count} " ;
                      if (i != count - 1)
                     {
                            await TaskEx .Delay( TimeSpan .FromSeconds(delayInSeconds), cancellationToken);
                     }
              }
       }
}

using System.Threading.Tasks;
using UnityEngine;
internal class ThreadPingPongDemo : MonoBehaviour
{
        public async void AsyncAwaitEventHandler()
       {
               AsyncTools .WhereAmI( "1" ); // main thread, Update context
               var task1 = Task .Factory.StartNew(() => AsyncTools .WhereAmI( "2" )); // background thread
               var task2 = new Task (() => AsyncTools .WhereAmI( "3" )); // main thread, FixedUpdate context
              task2.Start( UnityScheduler .FixedUpdateScheduler);
               var task3 = Task .Factory.StartNew(() => AsyncTools .WhereAmI( "4" )); // background thread
               // returns execution of asynchronous method to the main thread,
               // if it was originally called from the main thread
               await TaskEx .WhenAll(task1, task2, task3);
               AsyncTools .WhereAmI( "5" ); // main thread, Update context
               await TaskEx .Delay(100).ConfigureAwait( false );
               AsyncTools .WhereAmI( "6" ); // can be any thread, since the previous line states that we don't care
               Debug .Log( "done" );
       }
       
        public async void TaskContinueWithEventHandler()
       {
               AsyncTools .WhereAmI( "1" ); // main thread
               var originalTask = new Task (() => AsyncTools .WhereAmI( "2" ));
               var continuationTask1 = originalTask.ContinueWith(
                     previousTask => AsyncTools .WhereAmI( "3" ),
                      UnityScheduler .UpdateScheduler); // main thread, Update context
               var continuationTask2 = continuationTask1.ContinueWith(
                     previousTask => AsyncTools .WhereAmI( "4" )); // background thread
               var continuationTask3 = continuationTask2.ContinueWith(
                     previousTask => AsyncTools .WhereAmI( "5" ),
                      UnityScheduler .FixedUpdateScheduler); // main thread, FixedUpdate context
               var continuationTask4 = continuationTask3.ContinueWith(
                     previousTask => AsyncTools .WhereAmI( "6" )); // background thread
              originalTask.Start( UnityScheduler .ThreadPoolScheduler); // start the task chain from a background thread
               await continuationTask4;
               Debug .Log( "done" );
       }
       
        public void TaskRunSynchronouslyFromMainThreadEventHandler()
       {
               Debug .Log( "Launched from the main thread..." );
              RunTasksSynchronously();
               Debug .Log( "done" );
       }
        public async void TaskRunSynchronouslyFromBackgroundThreadEventHandler()
       {
               Debug .Log( "Launched from a background thread..." );
               await Task .Factory.StartNew(RunTasksSynchronously);
               Debug .Log( "done" );
       }
        private void RunTasksSynchronously()
       {
               /*
              Fact #1: ThreadPoolScheduler supports running tasks on any thread.
              Fact #2: MainThreadScheduler supports running tasks on the main thread only.
              If this method is called from the main thread, all the tasks will be executed on the main thread.
              
              If this method is called from a background thread, the tasks associated with the thread pool scheduler
              will be executed on the current background thread, and the tasks associated with the main thread scheduler will be
              executed on the main thread while the background thread will be blocked until the execution completes.
              */
               /*                   ATTENTION!!! ВНИМАНИЕ!!! ¡¡¡ATENCIÓN!!!
              Using UpdateScheduler, LateUpdateScheduler or FixedUpdateScheduler for running
              tasks synchronously from the main thread will cause a DEADLOCK if the current
              context doesn't match the task scheduler's type.
              E.g. don't call task.RunSynchronously(UnityScheduler.FixedUpdateScheduler) from
              the Update method.
              */
               AsyncTools .WhereAmI( "1" );
               var task = new Task (() => AsyncTools .WhereAmI( "2" ));
              task.RunSynchronously( UnityScheduler .UpdateScheduler);
              task = new Task (() => AsyncTools .WhereAmI( "3" ));
              task.RunSynchronously( UnityScheduler .ThreadPoolScheduler);
              task = new Task (() => AsyncTools .WhereAmI( "4" ));
              task.RunSynchronously( UnityScheduler .UpdateScheduler);
              task = new Task (() => AsyncTools .WhereAmI( "5" ));
              task.RunSynchronously(); // no scheduler => use default, which, in this case, is ThreadPoolScheduler
              task = new Task (() => AsyncTools .WhereAmI( "6" ));
              task.RunSynchronously( UnityScheduler .UpdateScheduler);
       }
       
        public async void ContextSwitchFromMainThreadEventHandler()
       {
               Debug .Log( "Launched from the main thread..." );
               await TestContextSwitch();
               Debug .Log( "done" );
       }
        public async void ContextSwitchFromBackgroundThreadEventHandler()
       {
               Debug .Log( "Launched from a background thread..." );
               await Task .Factory.StartNew( async () => await TestContextSwitch()).Unwrap();
               Debug .Log( "done" );
       }
        private static async Task TestContextSwitch()
       {
               AsyncTools .WhereAmI( "1" );
               await AsyncTools .ToThreadPool();
               AsyncTools .WhereAmI( "2" );
               await 0;
               AsyncTools .WhereAmI( "3" );
               await AsyncTools .ToUpdate();
               AsyncTools .WhereAmI( "4" );
               await 0;
               AsyncTools .WhereAmI( "5" );
               await AsyncTools .ToLateUpdate();
               AsyncTools .WhereAmI( "6" );
               await 0;
               AsyncTools .WhereAmI( "7" );
               await AsyncTools .ToFixedUpdate();
               AsyncTools .WhereAmI( "8" );
               await 0;
               AsyncTools .WhereAmI( "9" );
       }
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值