web-dev-qa-db-ja.com

EventHandlerイベントの発生を「待つ」方法

イベントパターンは、MVVMアプリケーションで、または子ビューモデルによってイベントを発生させて、このような疎結合の方法で親ビューモデルにメッセージを送信するために使用される場合があります。

親ViewModel

searchWidgetViewModel.SearchRequest += (s,e) => 
{
    SearchOrders(searchWidgitViewModel.SearchCriteria);
};

SearchWidget ViewModel

public event EventHandler SearchRequest;

SearchCommand = new RelayCommand(() => {

    IsSearching = true;
    if (SearchRequest != null) 
    {
        SearchRequest(this, EventArgs.Empty);
    }
    IsSearching = false;
});

アプリケーションを.NET4.5用にリファクタリングする際、asyncawaitを使用できる限り多くのコードを作成しています。ただし、以下は機能しません(まあ、実際には期待していませんでした)。

 await SearchRequest(this, EventArgs.Empty);

フレームワークはイベントハンドラーを呼び出すためにこれを確実に行います これなど が、それがどのように行われるかわかりませんか?

private async void button1_Click(object sender, RoutedEventArgs e)
{
   textBlock1.Text = "Click Started";
   await DoWork();
   textBlock2.Text = "Click Finished";
}

イベントを非同期に発生させることについて私が見つけたものは何でも isancient ですが、これをサポートするためにフレームワークで何かを見つけることができません。

イベントの呼び出しをawaitしながら、UIスレッドのままにするにはどうすればよいですか。

48
Simon_Weaver

Simon Weaver の答えを続けるために、私は以下を試しました

        if (SearchRequest != null)
        {
            foreach (AsyncEventHandler onSearchRequest in SearchRequest.GetInvocationList())
            {
                await onSearchRequest(null, EventArgs.Empty);
            }
        }

これはトリックを行うために縫い合わせます。

0
Ariel Steiner

これは@Simon_Weaverの回答から少し派生したものですが、私はそれが便利だと思います。イベント_RaisesEvents.MyEvent_を持つクラスRaisesEventsがあり、それをクラスMyClassに注入したとします。ここで、MyEventにサブスクライブし、Initialize()メソッドでサブスクライブすることをお勧めします。しかし、簡単にするために:

_public class MyClass
{
    public MyClass(RaisesEvent otherClass)
    {
        otherClass.MyEvent += MyAction;
    }

    private Action MyAction => async () => await ThingThatReturnsATask();

    public void Dispose() //it doesn't have to be IDisposable, but you should unsub at some point
    {
        otherClass.MyEvent -= MyAction;
    }

    private async Task ThingThatReturnsATask()
    {
        //async-await stuff in here
    }
}
_
0
Keith