Taskを使用した非同期処理のテスト
この記事は2017年07月15日にqiitaに投稿した内容です。
環境
Unity2017.1.0f3
概要
.NET4.6が使用できるようになったのでTask・Async/Awaitのテスト
.NET4.6の設定
「PlayerSettings」>「OtherSettings」>「ScriptRuntimeVertion」を「Experimental(.NET4.6Equivalent)」に変更する
プログラム
順次実行と並列実行をしています
Assets/TestTask.cs
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
public class TestTask : MonoBehaviour
{
[SerializeField] private Text _text = null;
private IEnumerator Start()
{
yield return new WaitForSeconds( 3.0f );
//順次実行
yield return StartCoroutine( TestTaskSequentialProcess() );
//並列実行
yield return StartCoroutine( TestTaskParallelProcess() );
}
private IEnumerator TestTaskSequentialProcess()
{
Debug.Log( "StartTestTaskSequential:" + Thread.CurrentThread.ManagedThreadId + "--------------------" );
var prevTime = Time.realtimeSinceStartup;
// var task = Task.Run( () => TaskSequential() );
var task = TaskSequential();
//task.Wait();//awaitのせいでデッドロックする
while( true )
{
if( task.IsCanceled == true || task.IsCompleted == true || task.IsFaulted == true )
break;
var time = Time.realtimeSinceStartup;
Debug.Log( "DeltaTime:" + ( time - prevTime ).ToString() );
prevTime = time;
yield return null;
}
Debug.Log( "CompleteTestTaskSequential" );
yield break;
}
private IEnumerator TestTaskParallelProcess()
{
Debug.Log( "StartTestTaskParallel:" + Thread.CurrentThread.ManagedThreadId + "--------------------" );
var prevTime = Time.realtimeSinceStartup;
//var task = Task.Run( () => TaskParallel() );
var task = TaskParallel();
//task.Wait(); //動作するが中身がわからないと使えないので使わない
while( true )
{
if( task.IsCanceled == true || task.IsCompleted == true || task.IsFaulted == true )
break;
var time = Time.realtimeSinceStartup;
Debug.Log( "DeltaTime:" + ( time - prevTime ).ToString() );
prevTime = time;
yield return null;
}
Debug.Log( "CompleteTestTaskParallel" );
yield break;
}
//Task.Run()で呼び出されなければ、呼び出し元と同じスレッドで実行される
//メインスレッドで実行されているならUnityの関数が使える
//awaitで待っている間、Taskは中断され、他に処理がうつる
private async Task TaskSequential()
{
Debug.Log( "StartTaskSequential:" + Thread.CurrentThread.ManagedThreadId );
if( _text != null )
_text.text = "StartTaskSequential";
for ( var i = 0; i < 5; i++ )
{
var index = i;
//awaitでTaskが終わるまで中断
await Task.Run(() => Sleep( index ) );
}
Debug.Log( "CompleteTaskSequential" );
}
private Task TaskParallel()
{
Debug.Log( "StartTaskParallel:" + Thread.CurrentThread.ManagedThreadId );
if( _text != null )
_text.text = "StartTaskParallel";
var tasks = new List<Task>();
for ( var i = 0; i < 5; i++ )
{
var index = i;
var task = Task.Run(() => Sleep( index ) );
tasks.Add( task );
}
//すべてのタスクが完了した時に完了するタスクを生成
var taskAll = Task.WhenAll( tasks );
//この時点では終わっていない
//ここで終わらせたければ asyncにしてawait Task.WhenAll()にする
Debug.Log( "CompleteTaskParallel" );
return taskAll;
}
private void Sleep( int index )
{
Debug.Log( "Sleep:" + Thread.CurrentThread.ManagedThreadId );
Thread.Sleep( 1000 );
Debug.Log( index );
}
}
Threadを用いた並列処理
Task・Async/Awaitを使用したくない場合 http://qiita.com/fukaken5050/items/c6ea9233b708082ae1e9
参考
http://qiita.com/acple@github/items/8f63aacb13de9954c5da http://qiita.com/takutoy/items/6f3a20f7f48f36d918dd