Action<Action> action = (Action action) => { action(); };
habrakatの下を見る前に、いくつかの質問に答えてみてください(投稿タイトルが表示されなかったふりをしましょう)。
- このコードはどの言語で書かれていますか?
- 彼は構文的に正しいですか? コンパイルされますか?
- このコードは理にかなっていますか? 彼は何をしていますか?
- なぜそのようなコードを書くことができたのですか
- このコードはどのように改善できますか? (どのように書きますか?)
- このコードの実際の使用例を示します。
- それを使用するときにどのような潜在的な問題が発生する可能性がありますか?
答えましたか? 次に、背景と説明のために、キャットの下に飛び込みます。
これは、.Net Framework 4.0でC#で記述された完全に機能するコードであることをすぐに言わなければなりません。 もちろん、意図的に面白いrebusに変更しました。製品コードでは次のようになります。
private Action<Action> doWork = work => { work(); };
ロシア語で言えば、別のデリゲートをパラメーターとして受け入れるデリゲートを作成します。 次に、理解しやすいように、既存のコードを可能な限り単純化して、彼がどのように生まれたかを説明します。 このようなコードがありました(すべての名前は架空のものであり、偶然の一致はランダムです)。
public class MyWorker { private void DoWorkInternal() { Thread.Sleep(1000);//simulate work IsWorkDone = true; } public void DoWork() { DoWorkInternal(); } public bool IsWorkDone { get; private set; } }
そして、作業の結果をチェックするテスト:
[TestMethod] public void TestDoWork() { MyWorker worker = new MyWorker(); Assert.IsFalse(worker.IsWorkDone); worker.DoWork(); Assert.IsTrue(worker.IsWorkDone); }
時間の経過とともに、戦闘状態では、
DoWorkInternal
メソッドが長時間実行され、その実行の結果がアプリケーションのさらなる動作に影響を与えないことが判明しました(ここで、何ができるかを推測できます)。 当然、実行を非同期にしたかったのです。
public void DoWork() { Task.Factory.StartNew(DoWorkInternal); }
そして、おそらくご想像のとおり、数十のテストを実施しましたが、テストは同期して行われると信じ続けていました。 テストを変更することは不適切であると考えました。 彼らは仕事を正しくやり遂げました(仕事の事実と結果を確認しました)。 さらに、1か月でこの作業が同期を必要とせず、すべてを元の形式に戻す必要があるという保証はまったくありませんでした。 状況を少し分析した後、ここでは作業を実行するための2つの戦略-同期実行と非同期を扱っていることを理解できます。 1つのメソッドを持つ戦略は、デリゲートに縮退します。
public class MyWorker { private Action<Action> doWork = work => { work(); }; private void DoWorkInternal() { Thread.Sleep(1000);//simulate work IsWorkDone = true; } public void DoWork() { doWork(DoWorkInternal); } public bool IsWorkDone { get; private set; } }
つまり 同期操作の戦略は次のとおりです。
(Action work) => { work(); }
非同期実行の戦略:
(Action work) => { Task.Factory.StartNew(work); }
クラスに、デフォルト(同期)戦略を別の戦略に変更できるメソッドを追加します。
public void SetDoWorkStrategy(Action<Action> doWork) { this.doWork = doWork; }
できた 証拠としてテストする:
[TestMethod] public void TestDoWork() { MyWorker worker = new MyWorker(); Assert.IsFalse(worker.IsWorkDone); worker.DoWork(); Assert.IsTrue(worker.IsWorkDone); MyWorker worker2 = new MyWorker(); Action<Action> asyncWorkStrategy = (Action work) => { Task.Factory.StartNew(work); }; worker2.SetDoWorkStrategy(asyncWorkStrategy); Assert.IsFalse(worker2.IsWorkDone); worker2.DoWork(); Assert.IsFalse(worker2.IsWorkDone);//work is in progress }
非同期戦略を使用する場合、コントロールへのアクセス、例外処理など、スレッド間の相互作用の機能を十分に理解する必要があります。 そうでなければ、副作用は避けられません。 これを終了します。誰かがこの記事をお役に立てば幸いです。
PS与えられたコードボアの議論は、.Net開発者の地位の候補者との会話に適したトピックです。