U3d 使用 异步 async await

来源:互联网 发布:程序员 1000万 编辑:程序博客网 时间:2024/06/14 06:44
 U3d 使用 异步 async await



官网:https://bitbucket.org/alexzzzz/unity-c-5.0-and-6.0-integration/src/e56c302fe239cf8818c0c02d23519f224a7bc891/CSharp60Support/?at=default

   1.1 下载 CSharp60Support 文件夹,里面包含需要的文件
               官网下载 https://bitbucket.org/alexzzzz/unity-c-5.0-and-6.0-integration/downloads?tab=downloads
                百度网盘: 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

演示 



usingUnityEngine;
usingSystem.Threading.Tasks;
//无返回值情况
classProgram:MonoBehaviour
{
   voidStart()
    {
        ExecuteAsync();//新建一个线程执行这个函数,不阻塞主线程,立即执行下面
       Debug.Log("start");
    }
    asyncvoidExecuteAsync()
    {
       awaitTaskEx.Run(() =>
        {
           Debug.Log("Async Executed");
        });
       Debug.Log("End");
    }
}

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


usingUnityEngine;
usingSystem.Threading.Tasks;
//有返回参数阻塞式
classProgram1:MonoBehaviour
{
   voidStart()
    {
       vart = ExecuteAsync();//新建一个线程执行这个函数
        t.Wait();//阻塞,一直等待函数执行完成
       Debug.Log("start");
        stringresult =t.Result;//返回值
    }
   asyncTask<string> ExecuteAsync()
    {
       awaitTaskEx.Run(() =>
        {
           Debug.Log("Async Executed");
        });
       Debug.Log("End");
       return"return Executed";
    }
}

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




usingUnityEngine;
usingSystem.Threading.Tasks;
publicclassTestt2:MonoBehaviour
{
       voidStart ()
       {
       YhyTools.LogTime("Test2 start join");
       vart = ShowRandomImages();
           t.Wait();
          stringresult =t.Result;//返回值
       YhyTools.LogTime("Test2 start end");
       }
   privateasyncTask<string> ShowRandomImages()
    {
       for(inti = 0; i < 9; i++)
        {
           awaitTaskEx.Delay(1000);//延迟一秒
           YhyTools.LogTime("ShowRandomImages");
        }
       return"1";
    }
}
输出结果:
                    


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



下面是官网例子

usingSystem;
usingSystem.Reflection;
usingUnityEngine;
usingUnityEngine.UI;
publicclassCrossPlatformTest:MonoBehaviour
{
       privatevoidStart()
       {
              Typetype =null;
              foreach(varassemblyinAppDomain.CurrentDomain.GetAssemblies())
              {
                     type = assembly.GetType("System.Threading.Platform");
                     if(type !=null)
                     {
                           break;
                     }
              }
              varmethodInfo = type.GetMethod("Yield",BindingFlags.Static |BindingFlags.NonPublic);
              ShowResult(false);
              methodInfo.Invoke(null,null);
              ShowResult(true);
       }
       privatestaticvoidShowResult(boolsuccess)
       {
              Camera.main.backgroundColor = success ? Color.green :Color.magenta;
              vartextObject = FindObjectOfType<Text>();
              textObject.text = success ?"SUCCESS":"FAIL";
       }
}

#ifUNITY_5
usingUnityEngine;
usingUnityEngine.EventSystems;
usingUnityEngine.Networking;
publicclassAsyncOperationAwaiterTest:MonoBehaviour,IPointerClickHandler
{
       privateTextureoriginalTexture;
       privateTexture2Dtexture;
       privateMaterialmaterial;
       publicasyncvoidOnPointerClick(PointerEventDataeventData)
       {
              Debug.Log("downloading...");
              varrequest =UnityWebRequest.Get("http://placeimg.com/512/512");
              awaitrequest.Send();
              Debug.Log("downloaded " + request.downloadedBytes +" bytes");
              texture.LoadImage(request.downloadHandler.data,true);
              material.mainTexture = texture;
       }
       privatevoidStart()
       {
              material = GetComponent<Renderer>().sharedMaterial;
              originalTexture = material.mainTexture;
              texture =newTexture2D(512, 512);
              Debug.Log("\n--> Click on the box to change its texture <--\n");
       }
       privatevoidOnDestroy()
       {
              Destroy(texture);
              material.mainTexture = originalTexture;
       }
       privatevoidUpdate()
       {
              transform.Rotate(0, 90 *Time.deltaTime, 0);
       }
}
#endif

usingUnityEngine;
usingUnityEngine.UI;
internalclassLogger:MonoBehaviour
{
   privateTexttextControl;
   privatevoidAwake()
    {
        textControl = GetComponent<Text>();
#ifUNITY_5
       Application.logMessageReceivedThreaded += Application_logMessageReceived;
#else
        Application.RegisterLogCallback(Application_logMessageReceived);
#endif
       Debug.Log("<color=red>Current platform: " +Application.platform +"</color>\n");
    }
   privatevoidApplication_logMessageReceived(stringmessage,stringstackTrace,LogTypetype)
    {
        textControl.text += message +"\n";
    }
}

usingSystem;
usingSystem.Threading;
usingSystem.Threading.Tasks;
usingUnityEngine;
usingUnityEngine.UI;
usingRandom= UnityEngine.Random;
publicclassSlideshowDemo:MonoBehaviour
{
       publicRawImagerawImage;
       publicTextcounterText;
       publicButtonstartButton;
       publicButtonabortButton;
       [Range(.1f, 5)]
       publicfloatdelayInSeconds = 1;
       privateTexture2Dtexture;
       privateCancellationTokenSourcetokenSource;
       privatevoidStart()
       {
              texture =newTexture2D(320, 200);
              rawImage.texture = texture;
       }
       privatevoidDestroy()
       {
              Destroy(texture);
       }
       publicasyncvoidStartSlideshow()// async methods can be on-click handlers, coroutines can't
       {
              tokenSource =newCancellationTokenSource();
              startButton.interactable =false;
              abortButton.interactable =true;
              try
              {
                     Debug.Log("Slideshow started");
                     awaitShowRandomImages(Random.Range(2, 21), tokenSource.Token);
                     Debug.Log("Run to completion");
              }
              catch(TaskCanceledException)
              {
                     Debug.Log("Aborted");
              }
              finally
              {
                     startButton.interactable =true;
                     abortButton.interactable =false;
              }
       }
       publicvoidAbortSlideshow()
       {
              abortButton.interactable =false;
              tokenSource.Cancel();
       }
       privateasyncTaskShowRandomImages(intcount,CancellationTokencancellationToken)
       {
              for(inti = 0; i < count; i++)
              {
                     varimage =awaitAsyncTools.DownloadAsBytesAsync("http://placeimg.com/320/200", cancellationToken);
                     texture.LoadImage(image);
                     rawImage.SetNativeSize();
                     counterText.text =$"{i + 1}of{count}";
                     if(i != count - 1)
                     {
                           awaitTaskEx.Delay(TimeSpan.FromSeconds(delayInSeconds), cancellationToken);
                     }
              }
       }
}

usingSystem.Threading.Tasks;
usingUnityEngine;
internalclassThreadPingPongDemo:MonoBehaviour
{
       publicasyncvoidAsyncAwaitEventHandler()
       {
              AsyncTools.WhereAmI("1");// main thread, Update context
              vartask1 =Task.Factory.StartNew(() =>AsyncTools.WhereAmI("2"));// background thread
              vartask2 =newTask(() =>AsyncTools.WhereAmI("3"));// main thread, FixedUpdate context
              task2.Start(UnityScheduler.FixedUpdateScheduler);
              vartask3 =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
              awaitTaskEx.WhenAll(task1, task2, task3);
              AsyncTools.WhereAmI("5");// main thread, Update context
              awaitTaskEx.Delay(100).ConfigureAwait(false);
              AsyncTools.WhereAmI("6");// can be any thread, since the previous line states that we don't care
              Debug.Log("done");
       }
       ////////////////////////////////////////////////////////////////////////////////////////////////////////////
       publicasyncvoidTaskContinueWithEventHandler()
       {
              AsyncTools.WhereAmI("1");// main thread
              varoriginalTask =newTask(() =>AsyncTools.WhereAmI("2"));
              varcontinuationTask1 = originalTask.ContinueWith(
                     previousTask =>AsyncTools.WhereAmI("3"),
                     UnityScheduler.UpdateScheduler);// main thread, Update context
              varcontinuationTask2 = continuationTask1.ContinueWith(
                     previousTask =>AsyncTools.WhereAmI("4"));// background thread
              varcontinuationTask3 = continuationTask2.ContinueWith(
                     previousTask =>AsyncTools.WhereAmI("5"),
                     UnityScheduler.FixedUpdateScheduler);// main thread, FixedUpdate context
              varcontinuationTask4 = continuationTask3.ContinueWith(
                     previousTask =>AsyncTools.WhereAmI("6"));// background thread
              originalTask.Start(UnityScheduler.ThreadPoolScheduler);// start the task chain from a background thread
              awaitcontinuationTask4;
              Debug.Log("done");
       }
       ////////////////////////////////////////////////////////////////////////////////////////////////////////////
       publicvoidTaskRunSynchronouslyFromMainThreadEventHandler()
       {
              Debug.Log("Launched from the main thread...");
              RunTasksSynchronously();
              Debug.Log("done");
       }
       publicasyncvoidTaskRunSynchronouslyFromBackgroundThreadEventHandler()
       {
              Debug.Log("Launched from a background thread...");
              awaitTask.Factory.StartNew(RunTasksSynchronously);
              Debug.Log("done");
       }
       privatevoidRunTasksSynchronously()
       {
              /*
              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");
              vartask =newTask(() =>AsyncTools.WhereAmI("2"));
              task.RunSynchronously(UnityScheduler.UpdateScheduler);
              task =newTask(() =>AsyncTools.WhereAmI("3"));
              task.RunSynchronously(UnityScheduler.ThreadPoolScheduler);
              task =newTask(() =>AsyncTools.WhereAmI("4"));
              task.RunSynchronously(UnityScheduler.UpdateScheduler);
              task =newTask(() =>AsyncTools.WhereAmI("5"));
              task.RunSynchronously();// no scheduler => use default, which, in this case, is ThreadPoolScheduler
              task =newTask(() =>AsyncTools.WhereAmI("6"));
              task.RunSynchronously(UnityScheduler.UpdateScheduler);
       }
       ////////////////////////////////////////////////////////////////////////////////////////////////////////////
       publicasyncvoidContextSwitchFromMainThreadEventHandler()
       {
              Debug.Log("Launched from the main thread...");
              awaitTestContextSwitch();
              Debug.Log("done");
       }
       publicasyncvoidContextSwitchFromBackgroundThreadEventHandler()
       {
              Debug.Log("Launched from a background thread...");
              awaitTask.Factory.StartNew(async() =>awaitTestContextSwitch()).Unwrap();
              Debug.Log("done");
       }
       privatestaticasyncTaskTestContextSwitch()
       {
              AsyncTools.WhereAmI("1");
              awaitAsyncTools.ToThreadPool();
              AsyncTools.WhereAmI("2");
              await0;
              AsyncTools.WhereAmI("3");
              awaitAsyncTools.ToUpdate();
              AsyncTools.WhereAmI("4");
              await0;
              AsyncTools.WhereAmI("5");
              awaitAsyncTools.ToLateUpdate();
              AsyncTools.WhereAmI("6");
              await0;
              AsyncTools.WhereAmI("7");
              awaitAsyncTools.ToFixedUpdate();
              AsyncTools.WhereAmI("8");
              await0;
              AsyncTools.WhereAmI("9");
       }
}



0 0