TemporarySynchronizationContext をローカルクラスに格下げ

This commit is contained in:
ousttrue 2021-02-17 12:41:56 +09:00
parent 701d44acc9
commit 4c59fe3ebe
3 changed files with 53 additions and 68 deletions

View File

@ -1,4 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace UniGLTF
@ -27,22 +30,71 @@ namespace UniGLTF
self.Root.name = Path.GetFileNameWithoutExtension(path);
}
class TemporarySynchronizationContext : SynchronizationContext
{
Queue<Action> m_callbacks = new Queue<Action>();
/// <summary>
/// await して中断された継続がここにくる。
///
/// ex. await Task.Run(() =>{ /* ここ */ });
/// </summary>
/// <param name="d"></param>
/// <param name="state"></param>
public override void Post(SendOrPostCallback d, object state)
{
// Debug.Log($"Post");
m_callbacks.Enqueue(() => d(state));
}
/// <summary>
/// 一個デキューして実行する。
/// Unityであれば毎フレームこのように消化しているであろう。
///
/// https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Scripting/UnitySynchronizationContext.cs
/// </summary>
/// <returns></returns>
public bool ExecuteOneCallback()
{
while (m_callbacks.Count == 0)
{
// Debug.Log($"empty callbacks");
return false;
}
var callback = m_callbacks.Dequeue();
callback();
return true;
}
}
/// <summary>
/// Build unity objects from parsed gltf
/// </summary>
public static void Load(this ImporterContext self)
{
var tcs = new TemporarySynchronizationContext();
using (tcs.Hijack())
// 元に戻すためバックアップ
var backup = SynchronizationContext.Current;
// 一時的に変更
SynchronizationContext.SetSynchronizationContext(tcs);
try
{
var task = self.LoadAsync();
// 中断された await を消化する
while (!task.IsCompleted)
{
// execute synchronous
tcs.ExecuteOneCallback();
}
}
finally
{
// 元に戻す
SynchronizationContext.SetSynchronizationContext(backup);
}
}
}
}

View File

@ -1,56 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
namespace UniGLTF
{
/// <summary>
/// await で post される先を1次的に乗っ取る
/// </summary>
public class TemporarySynchronizationContext : SynchronizationContext
{
Queue<Action> m_callbacks = new Queue<Action>();
public override void Post(SendOrPostCallback d, object state)
{
// Debug.Log($"Post");
m_callbacks.Enqueue(() => d(state));
}
public bool ExecuteOneCallback()
{
while (m_callbacks.Count == 0)
{
// Debug.Log($"empty callbacks");
return false;
}
var callback = m_callbacks.Dequeue();
callback();
return true;
}
class Hijacker : IDisposable
{
SynchronizationContext m_backup;
public Hijacker(SynchronizationContext context)
{
m_backup = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(context);
}
public void Dispose()
{
SynchronizationContext.SetSynchronizationContext(m_backup);
}
}
public IDisposable Hijack()
{
return new Hijacker(this);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 62f8f380aadfc284f9bdc2d58f84bf48
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: