2013-03-06 74 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是必需的。