フレームワークのユーザーがノンブロッキング関数 (別名「コルーチン」) を備えた言語として C# を使用できるフレームワークを拡張しようとしています。私の最初の設計yield return
では、関数の戻り値としてステートメントと IEnumerator を使用しました。
ただし、別のyield関数を呼び出そうとすると(さらに、他の関数が値を返す必要がある場合)、これはかなりエラーが発生しやすく、使いにくいです。
そのため、私はコルーチンを使用async
しawait
て提供するというアイデアをいじっています。結果として得られる構文は、はるかに楽しいものになるでしょう。
私たちのフレームワークでは、これらのノンブロッキング スクリプトが 2 つ同時に実行されないようにする必要があるため、SynchonizationContext
すべてのアクションを自分でスケジュールする独自のスクリプトを作成しました。それは魅力のように機能します。
さらに興味深いのは、私たちの設計のもう 1 つの重要な部分は、失敗した場合に「現在の」実行中の機能を続行しない何らかの「チェック機能」をユーザーが登録できることです。チェック関数は、ノンブロッキング関数が再開するたびに実行する必要があります。
たとえば、次のようになります。
async Task DoSomething()
{
var someObject = SomeService.Get(...);
using (var check = new SanityCheckScope())
{
check.StopWhen(() => someObject.Lifetime < 0);
...
await SomeOtherStuff();
// when execution comes back in here, the StopWhen - condition above should be
// evaluated and the Task should not be scheduled if its true.
...
}
}
SomeOtherStuff
それによって呼び出された非同期関数が再開するたびに、登録された条件をチェックしDoSomething
、いずれかの条件が true の場合は停止する必要があります。
これを実装するために、SynchonizationContext は登録された関数 ( を介して渡されるCallContext.LogicalSetData
) をチェックし、true が返された場合はタスクをスケジュールしません。
ここで厄介な問題が発生します。関数SomeOtherStuff
が次のようになっているとします。
async Task SomeOtherStuff()
{
using (var check = new SanityCheckScope())
{
// register my own check functions
await Whatever();
}
}
例ではSomeOtherStuff
、独自のチェック関数を登録します。の後に true の場合はawait Whatever()
、当然、SomeOtherStuff
関数のみを停止する必要があります。( SomeOtherStuff が を返す場合、が戻り値として使用されTask<XXX>
ても問題ないと仮定しましょう。)default(XXX)
どうすればこれにアプローチできますか?await SomeOtherStuff();
元の関数の の後に来る Action にたどり着けません。どちらかの先頭にフックやコールバックがないようですawait
(とにかく意味がありません)。
別のアイデアは、タスクを「スケジュールしない」のではなく、例外をスローすることです。-blockの代わりに (または追加して)、using
try/catch を記述します。ただし、元 DoSomething
のチェック機能がインナーの後に失敗した場合、await Whatever();
どのように停止するかという問題が発生しましたDoSomething
(一緒にSomeOtherStuff
)?
だから私がこれをすべてスクラッチして私のものに戻る前にIEnumerator
..これが/フレームワークyield return
でできるかどうか誰かが考えましたか?async
await