2013-03-06 22 views
10

Tôi gặp vấn đề này với phương thức trong C#. Tôi đã thực hiện một phương thức gọi một hàm từ một dll được gọi là Phone.GetLampMode(); Bây giờ Phone.GetLampMode không trả lại bất kỳ điều gì. Dữ liệu được trả về trong sự kiện 'onGetLampModeResponse' sự kiện. Có cách nào tôi có thể chờ đợi trong phương pháp của tôi cho đến khi tôi nhận được dữ liệu từ sự kiện onGetLampModeResponse?Đợi phương thức bên trong cho đến khi sự kiện được chụp

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

tham số thứ hai của GetLampMode là gì? Hãy để tôi đoán: Một đối tượng mà bạn có thể xác định chính mình? Và đó là đối tượng 'người gửi' trong trình xử lý sự kiện hay bên trong' e'? EDIT: Vâng, nó được gọi là userState. Bạn có thể lấy userState này bên trong biến 'e' trong hàm gọi lại. – sinni800

+0

Tôi có thể nghĩ ra một giải pháp xấu bằng cách định nghĩa một 'bool' toàn cục được đặt thành' true' bởi 'OnGetLampModeResponse' và được kiểm tra trong một vòng lặp bằng' checkLamp'. –

+0

@JohnWillemse khá xấu và không nên được thực hiện vì khái niệm về việc trao các biến trạng thái cho các sự kiện tồn tại. – sinni800

Trả lời

9

Một giải pháp là sử dụng 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(); 
} 

LƯU Ý: Quảng cáo bạn đang sử dụng Phone như là một lớp/biến tĩnh, người ta có thể nghĩ rằng bạn đang phát triển trên Windows Phone ... Nếu đúng như vậy, hãy lưu ý rằng toàn bộ khái niệm về WP và lập trình không đồng bộ là không khóa luồng giao diện người dùng theo cách như vậy.

+2

Bạn vừa đặt waitHandle vào bối cảnh chung? Điều gì sẽ xảy ra nếu bạn thực thi nó nhiều hơn một lần và chờ đợi hoàn toàn bị kẹt? Làm thế nào có thể câu trả lời này thậm chí có được upvotes? – sinni800

+0

@ sinni800 Nhận xét hay, nhưng OP không chỉ rõ bất cứ điều gì về đa luồng. Tôi nghĩ anh ấy chỉ muốn làm một cái gì đó đồng bộ từ async. Nếu nó thực sự là đa luồng, xử lý chờ đợi sẽ được chuyển như một tham số của phương thức. – ken2k

+0

nó chắc chắn sẽ được thông qua như userState, trong mọi trường hợp. Bạn có nguy cơ nhận được một sợi bị mắc kẹt vô hạn vì những thứ như vậy là "điều kiện chủng tộc". – sinni800

0

Có vẻ như mô hình hiện tại gần với Mẫu không đồng bộ dựa trên sự kiện (EAP). Bạn có thể muốn xem bài viết Interop with Other Asynchronous Patterns and Types mô tả cách chuyển đổi mẫu như vậy thành Mẫu Async dựa trên Nhiệm vụ mới hơn (TAP).

Một khi bạn có một Task (hoặc Task<T>, bạn có thể chỉ Wait cho nó

+0

Vâng, các từ khóa Async sẽ hoàn hảo .. – sinni800

2

Bạn có thể quấn xử lý trong một phương pháp không đồng bộ, mà nên tìm kiếm một cái gì đó như thế này (chưa được kiểm tra):.

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

Trong phương thức gọi, bạn sẽ viết:

Điều này có lợi thế là giao diện người dùng của bạn không chặn trong khi quá trình chờ phản hồi.

Đây là mục nhập blog về vấn đề này. Lưu ý rằng Framework 4.5 là bắt buộc.

Các vấn đề liên quan