c# - 待っているラムダ

c# .net delegates lambda async-await

キーリスナーでの動的評価

public class KeyUpper {
    Func<Key, bool> _evaluate;

    public void RegisterEvaluator(Func<Key, bool> evaluate){
        _evaluate = evaluate;
    }

    public void KeyUp(object sender, KeyEventArgs e){
        if (_evaluate(e.KeyCode))
            SomeResponse();
    }

    public void SomeResponse(){
        // ...
    }
}


このラムダは各行で待機する必要があります

keyUpper.RegisterEvaluator(key => 
    {
    if (key == Key.A)
        if (key == Key.W)
            if (key == Key.A)
                return true;
    }
);



つまり、クライアントコードは、同じkey引数に一連の評価を提供します。評価の各行は、1:A 2:W 3の一連のキーアップイベントの後にSomeResponse()が呼び出されるように待機することを期待しています。あ
メソッドが最後まで実行され、key == Key.Wが真になることはないため、決して起こり得ない現時点では明らかに
それは可能ではないかもしれませんが、メソッド呼び出しがfalseと評価された場合に次の行から自動的に戻り、その行がtrueと評価されるまで戻り、その後、次の行、そしてその後のメソッドの終わりまでの行?
つまり、この種の待機可能なラムダ式を提供する簡単な方法があるでしょうか?
答え
非同期性が要件ではなく、ほぼ常に待機する1つのスレッドで問題がない場合は、ラムダにキーにアクセスするためのいくつかのブロック方法を与えることによってそれを行うことができます。例えば:

public void RegisterEvaluator(Func<Func<Key>, bool> evaluate);

…

keyUpper.RegisterEvaluator(
    getKey => getKey() == Key.A && getKey() == Key.W);


次に、RegisterEvaluatorはループでラムダを呼び出す新しいスレッドを起動し、キーにアクセスするメソッドを渡します。たとえば、BlockingCollection<Key>を使用して、現在使用できるキーがない場合はブロックします。

この方法で行うのはもったいない(そうである)と考え、async-awaitを使用できる場合は、ラムダasyncを作成して、渡されたメソッドを非同期のメソッドに変更します。

public Task RegisterEvaluator(Func<Func<Task<Key>>, Task<bool>> evaluate);

…

keyUpper.RegisterEvaluator(
    async getKey => await getKey() == Key.A && await getKey() == Key.W);


後者のバージョンの実装(BlockBuffer<Key>を使用)は次のようになります。

class KeyUpper
{
    private readonly BufferBlock<Key> m_keyBuffer = new BufferBlock<Key>();

    public async Task RegisterEvaluator(
        Func<Func<Task<Key>>, Task<bool>> evaluate)
    {
        while (true)
        {
            if (await evaluate(m_keyBuffer.ReceiveAsync))
                SomeResponse();
        }
    }

    public void KeyUp(object sender, KeyEventArgs e)
    {
        m_keyBuffer.Post(e.Key);
    }

    private void SomeResponse()
    {
        // whatever
    }
}


さて、キーのマッチングをどのように正確に処理したいのかはわかりませんが、これはそうではないと思います。たとえば、このサンプルコードはキーのシーケンスBAWに一致しますが、AAWには一致しません。

別のオプションはFunc<Task<Key>>を使用しないことですが、複数回待機することができ、それを実行するたびに1つのキーを提供するカスタムのawaitable:

public Task RegisterEvaluator(Func<KeyAwaitable, Task<bool>> evaluate);

…

keyUpper.RegisterEvaluator(
    async getKey => await getKey == Key.A && await getKey == Key.W);


しかし、私はそれをこの方法で行うと、より混乱し、実行するのが難しくなると思います。
関連記事

c# - ウィンドウのPNGスクリーンショットを撮るが、空気透過性は維持する

c# - 非ブロッキングブロックからブロッキングコードを呼び出すときの制御の流れを理解していますか?

c# - IronPythonでILMergeを使用する

c# - ListViewオブジェクト参照がオブジェクトのインスタンスに設定されていません

c# - コンバーターを使用してWPF ContextMenuをObservableCollectionにバインドする際の問題

c# - 異なるテキスト配置のListView?

c# - C#クラスの設計-「プロジェクト」クラスの配置を検討すべき場所

c# - 1人のユーザーのデータベースでトランザクションが必要ですか? [閉まっている]

c# - IDでXmlノードを取得する最も速い方法は何ですか

c# - MSB0001:内部MSBuildエラー:refCountは1未満であってはなりません