2013-03-06 6 views
10

私はこの問題をC#のメソッドで持っています。私は、呼び出されたDLLから関数を呼び出すメソッドを作ったPhone.GetLampMode();Phone.GetLampModeは何も返しません。データは 'onGetLampModeResponse'というイベントで返されます。 onGetLampModeResponseイベントからデータを取得するまで私のメソッドで待つことができる方法はありますか?イベントがキャプチャされるまで内部メソッドを待つ

public bool checkLamp(int iLamp) 
{ 
    Phone.ButtonIDConstants btn = new Phone.ButtonIDConstants(); 
    btn = Phone.ButtonIDConstants.BUTTON_1; 
    btn += iLamp; 
    Phone.GetLampMode(btn, null); 

    return true; 
} 

private void Phone_OnGetLampModeResponse(object sender, Phone.GetLampModeResponseArgs e) 
{ 
    var test = e.getLampModeList[0].getLampMode.ToString();  
} 
+1

GetLampModeの2番目のパラメータは何ですか?私に推測させてください:自分で定義できるオブジェクト?そしてそのオブジェクトは、イベントハンドラの 'sender'か' e'の内部ですか?編集:そうです、それはuserStateと呼ばれています。コールバック関数の 'e'変数の中でこのuserStateを取り出すことができます。 – sinni800

+0

私は 'OnGetLampModeResponse'によって' true'に設定され、 'checkLamp'によってループでチェックされるグローバルな' bool'を定義することによって、醜い解決策を考えることができます。 –

+0

@JohnWillemseこれはかなり醜いので、状態変数をイベントに渡すという概念が存在するので、実行すべきではありません。 – sinni800

答えて

9

一つの解決策はAutoResetEventを使用することです:

public bool checkLamp(int iLamp) 
{ 
    Phone.ButtonIDConstants btn = new Phone.ButtonIDConstants(); 
    btn = Phone.ButtonIDConstants.BUTTON_1; 
    btn += iLamp; 

    AutoResetEvent waitHandle = new AutoResetEvent(false); 

    // Pass waitHandle as user state 
    Phone.GetLampMode(btn, waitHandle); 

    // Wait for event completion 
    waitHandle.WaitOne(); 

    return true; 
} 

private void Phone_OnGetLampModeResponse(object sender, Phone.GetLampModeResponseArgs e) 
{ 
    var test = e.getLampModeList[0].getLampMode.ToString(); 

    // Event handler completed 
    // I guess there is some UserState property in the GetLampModeResponseArgs class 
    ((AutoResetEvent)e.UserState).Set(); 
} 

注:静的クラス/変数としてPhoneを使用している 広告は、1は、Windows Phoneで開発していると考えることができます...その場合、WPと非同期プログラミングの概念全体は、のようにUIスレッドをロックしないでください。です。

+2

waitHandleをグローバルコンテキストに配置しましたか?あなたが何度もそれを実行し、あなたの待ち時間が完全に止まったらどうなるでしょうか?この回答はどのようにアップアップを得ることができますか? – sinni800

+0

@ sinni800良いコメントですが、OPはマルチスレッドについて何も指定していませんでした。私は彼がただ非同期から何かを同期させたいと思うと思う。実際にマルチスレッドの場合は、メソッドのパラメータとして待機ハンドルを渡す必要があります。 – ken2k

+0

必ずどんな場合でもuserStateとして渡す必要があります。あなたは、「競合状態」のような些細なことのために、スレッドを無限に詰まらせる危険性があります。 – sinni800

0

既存のモデルがイベントベースの非同期パターン(EAP)に近いようです。このようなパターンを新しいタスクベースの非同期パターン(TAP)に変換する方法については、記事Interop with Other Asynchronous Patterns and Typesを参照してください。

あなたはそれのためにTask(またはTask<T>、あなたができるだけWaitを持っていたら

+0

ええ、非同期キーワードは完璧です。 – sinni800

2

あなたはテストされていないこのようなものを()はず非同期方式でハンドラをラップすることができます。

public async Task<bool> checkLamp(int iLamp) 
{ 
    Phone.ButtonIDConstants btn = new Phone.ButtonIDConstants(); 
    btn = Phone.ButtonIDConstants.BUTTON_1; 
    btn += iLamp; 

    var tcs = new TaskCompletionSource<bool>(); 
    var handler = (sender, e) => { 
     Phone.OnGetLampModeResponse -= handler; 
     var test = e.getLampModeList[0].getLampMode.ToString(); 
     tcs.SetResult(true); 
    }; 
    Phone.OnGetLampModeResponse += handler; 

    Phone.GetLampMode(btn, null); 

    return tcs.Task; 
} 
あなたの呼び出し方法で

は、次のように記述します。これは利点ユーザーインターフェイスの雌ジカを持つ

プロセスが応答を待っている間はブロックされません。

ここにこの問題に関するブログエントリがあります。フレームワーク4.5が必要であることに注意してください。

関連する問題