【问题标题】:Trying to make method wait for internal event handling finished试图让方法等待内部事件处理完成
【发布时间】:2013-11-07 20:18:09
【问题描述】:

我是 C# async/await 的新手,在尝试使用异步方法时遇到了一些问题。 我有一个收藏:

private IList<IContactInfo> _contactInfoList

还有一个异步方法:

public async Task<IList<IContactInfo>> SelectContacts()
{
    _contactInfoList = new List<IContactInfo>();
    ContactsSelector selector = new ContactsSelector();
    selector.ShowPicker();

    selector.ContactsSelected += (object sender, ContactsSelectorEventArgs e) =>
    {
        this._contactInfoList = e.Contacts;                
    };

    return _contactInfoList;
}

联系人选择器是一个弹出式用户控件,允许从手机中选择一些联系人,点击“确定”按钮后会触发ContactsSelected 事件。我需要从事件参数e.Contacts 中获取选定的联系人列表,并在上面提到的SelectContacts() 异步方法中返回该列表。这就是问题所在:在ContactsSelected 事件完成他的工作之前,我的方法已经返回空列表_contactInfoList。我知道在这种情况下 async/await 甚至无关紧要,这个问题在通常的方法中会存在,但我只需要让那个方法等待事件处理结果。

【问题讨论】:

    标签: c# .net windows-phone-8 task-parallel-library async-await


    【解决方案1】:

    这里需要做的是将异步编程的事件样式转换为异步编程的任务样式。使用TaskCompletionSource 使这变得相当简单。

    public static Task<IList<IContactInfo>> WhenContactsSelected(
        this ContactsSelector selector)
    {
        var tcs = new TaskCompletionSource<IList<IContactInfo>>();
        selector.ContactsSelected += (object sender, ContactsSelectorEventArgs e) =>
        {
            tcs.TrySetResult(e.Contacts);
        };
        return tcs.Task;
    }
    

    现在我们有了一个方法,它返回一个任务并返回我们需要的结果,使用它的方法非常简单:

    public Task<IList<IContactInfo>> SelectContacts()
    {
        ContactsSelector selector = new ContactsSelector();
        selector.ShowPicker();
    
        return selector.WhenContactsSelected();
    }
    

    这里有几点需要注意。首先,我删除了实例字段;这在这里似乎是个坏主意。如果SelectContacts 被多次调用,将导致两人争夺该领域。从逻辑上讲,如果您确实需要存储列表,它应该是一个局部变量。接下来,这里没有await 使用,因此该方法不应标记为async。如果你想await 打电话给WhenContactsSelected 然后随时添加async,但到目前为止我认为没有真正需要它。

    【讨论】:

    • @Servy,你为什么用TrySetResult而不是SetResult?在事件处理程序中添加try/catch,在try 中调用tcs.SetResult,在catch 中调用tcs.SetException 是否是个好主意?
    猜你喜欢
    • 1970-01-01
    • 2021-12-08
    • 2011-07-05
    • 1970-01-01
    • 2021-11-30
    • 2021-03-04
    • 1970-01-01
    • 2016-08-17
    • 1970-01-01
    相关资源
    最近更新 更多