2013-03-06 40 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的第二個參數?讓我猜猜:你可以定義自己的對象?那麼這個對象是事件處理程序中的'sender'還是'e'中的?編輯:是的,它被稱爲userState。您可以在回調函數中的'e'變量中檢索此userState。 – sinni800 2013-03-06 09:00:41

+0

我可以通過定義由'OnGetLampModeResponse'設置爲TRUE;並通過'checkLamp'循環檢查全局'bool'想到一個醜陋的解決方案。 – 2013-03-06 09:01:40

+0

@JohnWillemse這是相當醜陋的,不應該這樣做,因爲把狀態變量交給事件存在。 – sinni800 2013-03-06 09:03:59

回答

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作爲一個靜態類/變量的廣告,可以認爲你在Windows Phone開發...如果是的話,就請注意,WP和異步編程的整個概念是以這樣的方式沒有鎖定UI線程。

+2

你剛剛把waitHandle放到全局上下文中嗎?如果你多次執行它並讓你的等待完全卡住,該怎麼辦?這個答案怎麼能得到upvotes? – sinni800 2013-03-06 09:07:57

+0

@ sinni800好評,但OP沒有指定關於多線程的任何內容。我想他只是想從異步中進行同步。如果它實際上是多線程的,則應該將等待句柄作爲方法的參數傳遞。 – ken2k 2013-03-06 09:09:41

+0

它絕對應該作爲userState傳遞,在任何情況下。由於諸如「競爭條件」之類的麻煩事情,你可能無法無限地陷入困境。 – sinni800 2013-03-06 09:10:52

0

它看起來像現有的模型是接近基於事件的異步模式(EAP)。您可能需要查看文章Interop with Other Asynchronous Patterns and Types,其中描述瞭如何將這種模式轉換爲較新的基於任務的異步模式(TAP)。

一旦你有一個Task(或Task<T>,你可以Wait

+0

是的,異步關鍵字將是完美的.. – sinni800 2013-03-06 09:40:01

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; 
} 

在您的調用方法,你可以這樣寫:

這樣的優點在於用戶界面母鹿當進程正在等待響應時,它不會阻塞。

下面是關於這個問題的博客條目。請注意,Framework 4.5是必需的。