如何将异步联系人搜索的结果传递回调用方法?

时间:2011-10-29 10:27:29

标签: c# asynchronous contacts windows-phone-7.1

我正在尝试编写一个抓取联系人的方法,并将其转换为数据对象并返回它。据我所知,由于联系人搜索是异步的,因此调用方法也需要;但是,我想返回一个对象作为调用搜索的父方法的一部分,我不太确定最好的方法是什么。

我目前得到的伪代码是:

public Person GetRandomPerson(string s)
{
    Person myPerson = new Person();

    Person contacts = new Contacts();            

    contacts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(contacts_SearchCompleted);
    contacts.SearchAsync(String.Empty, FilterKind.None, "All Contacts");            

    return Person;    //I'm not sure how this will ever work...
}

void contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
    //convert a Contact object to Person object here
}

我已经在这个地方做了一些阅读(like this SO question)但是我不太确定嵌套的异步返回调用是怎么样的,或者我是如何从基于事件传递结果的异步联系人搜索回到父调用方法 - 我将如何实现这种效果?

2 个答案:

答案 0 :(得分:1)

我稍微更改了你的代码。您需要PersonGetRandomPerson之间的共享课程contacts_SearchCompleted。查看contacts.SearchAsync的参数,也许您可​​以将myPerson传递给它而不声明为class'es私有字段。

Person myPerson = new Person(); //*****
public Person GetRandomPerson(string s)
{
    Person contacts = new Contacts();            

    contacts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(contacts_SearchCompleted);
    contacts.SearchAsync(String.Empty, FilterKind.None, "All Contacts");            

    wait.WaitOne();      //*****
    return myPerson;    //I'm not sure how this will ever work...
}

ManualResetEvent wait = new ManualResetEvent(false); //*****

void contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
    //Fill myPerson
    wait.Set(); //*****
}

答案 1 :(得分:0)

好吧,我终于解决了,解决方案有两个部分:

1)将我想创建的DataObject传递给联系人搜索结果作为.SearchAsync方法调用中的第三个对象状态参数。

2)将GetRandomPerson(最初只是一个Button_Click)的调用移动到后台线程;在这种情况下,我使用 ThreadPool.QueueUserWorkItem 。从 WaitOne()看来,UI线程似乎无法很好地恢复。

如果您有兴趣,工作代码解决方案是:

private void Button_Click(object sender, RoutedEventArgs e)
{
    //this should be done asynchronously - "request" a person

    List<Person> people = new List<Person>();
    PersonService ps = new PersonService();     
    ThreadPool.QueueUserWorkItem(func =>
    {
        for (int i = 0; i < 10; i++)
        {
                    people.Add(ps.GetRandomPerson()); //you need to call this on a separate thread or it will lock the ui thread.                       
        }                                   
        Dispatcher.BeginInvoke(() => { Status.Text = "done"; });    //your button click method is now also asynchronous
    });
}

/*** Helper class ***/      

public class PersonService
{
    AutoResetEvent sync = new AutoResetEvent(false);

    public Person GetRandomPerson()
    {
        Person person = new Person();
        Contacts contacts = new Contacts();            
        contacts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(contacts_SearchCompleted);            
        contacts.SearchAsync(String.Empty, FilterKind.None, person);
        sync.WaitOne();
        return person;
    }

    void contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
    {
        Contact[] allContacts = e.Results.ToArray();
        Contact randomContact = allContacts[new Random().Next(allContacts.Length)];
        Person person = (Person)e.State;
        person.Name = randomContact.DisplayName;

        sync.Set();
    }
}

我仍然有兴趣听听是否有人对此有更优雅的解决方案,所以如果你有一个,请大声喊出来!