Skip to content

Commit

Permalink
feat: awaiter completed checker
Browse files Browse the repository at this point in the history
  • Loading branch information
labbbirder committed Jul 7, 2023
1 parent 6d79dcc commit d35bfe7
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 12 deletions.
43 changes: 40 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,13 @@ public class Demo:MonoBehaviour{
FixHelper.Install();
}

void Update(){
async void Update(){
if(Input.GetKeyDown(KeyCode.A)){
Work(2,"aka");
Work(1,"foo");
}
if(Input.GetKeyDown(KeyCode.S)){
AsyncWork(2,"aka");
await AsyncWork(2,"bar");
print("return");
}
}

Expand All @@ -151,6 +152,42 @@ public class Demo:MonoBehaviour{
}
}
```
### 异步方法补充说明
async方法有一个值得斟酌的问题。如果上例的Task换成UniTask。则不会打印return,这是因为Decrote方法覆盖了原本的continuationAction(这与UniTask的实现有关)。使用如下Decorate方法可以解决所有此类问题:
```csharp
protected override R Decorate<R>(InvocationInfo<R> invocation)
{
Debug.Log("begin "+info+string.Join(",",invocation.Arguments));
var r = invocation.FastInvoke();
if(IsAsyncMethod)
{
// delay when its an async method
var awaiter = invocation.GetAwaiter(r);
UniTask.Create(async()=>
{
try
{
while(!invocation.IsAwaiterCompleted(awaiter))
await UniTask.Yield();
}
catch {}
finally
{
OnCompleted();
}
});
// invocation.GetAwaiter(r).OnCompleted(OnCompleted);
}
else
{
OnCompleted();
}
return r;
}
```
上例使用`UniTask.Create`创建了一个轮询器,可以使用其他类似的轮询方法,如自定义MonoBehaviour。一旦`IsAwaiterCompleted`检查结束,立即执行自定义的`OnCompleted`方法。

因为Unity没有官方支持的异步轮询接口,基于“此库只做自己该做的”原则,这里只是给出提示。

更多使用方法参考附带的Sample工程

Expand Down
17 changes: 17 additions & 0 deletions Runtime/DecoratorAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.Assertions;

namespace com.bbbirder.unity{
[AttributeUsage(AttributeTargets.Method)]
Expand Down Expand Up @@ -64,6 +65,7 @@ public bool IsAsyncMethod
public struct InvocationInfo<T>{
internal Func<T> invoker;
internal Func<INotifyCompletion> awaiterGetter;
internal Func<bool> awaiterCompletedChecker;
internal Func<object[]> argumentGetter;

/// <summary>
Expand Down Expand Up @@ -105,6 +107,21 @@ public struct InvocationInfo<T>{
if(awaiterGetter is null) return null;
return awaiterGetter();
}

public bool IsAwaiterCompleted(INotifyCompletion awaiter){
string memberName = "IsCompleted";
Assert.IsNotNull(awaiter,"awaiter is null");
if(awaiterCompletedChecker is null){
var awaiterType = awaiter.GetType();
var propChecker = awaiterType.GetProperty(memberName);

if(propChecker != null){
awaiterCompletedChecker = (Func<bool>)propChecker.GetMethod.CreateDelegate(typeof(Func<bool>),awaiter);
}
}
Assert.IsNotNull(awaiterCompletedChecker,"cannot create delegate for "+memberName);
return awaiterCompletedChecker.Invoke();
}
internal Func<INotifyCompletion> MetaGetAwaiter<N>(MethodInfo method,T target) where N:INotifyCompletion{
var func = method.CreateDelegate(typeof(Func<N>),target) as Func<N>;
return ()=>func();
Expand Down
8 changes: 0 additions & 8 deletions Samples.meta

This file was deleted.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "com.bbbirder.injection",
"displayName": "Unity Injection",
"description": "Unity注入模块,可以运行时改变被注入函数实现。",
"version": "1.1.4",
"version": "1.1.13",
"hideInEditor": false,
"author": "bbbirder <502100554@qq.com>",
"dependencies": {
Expand Down

0 comments on commit d35bfe7

Please sign in to comment.