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

发布于 2024-12-12 17:59:06 字数 881 浏览 1 评论 0原文

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

我目前得到的伪代码是:

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
}

我已经在这个地方做了一些阅读(像这样的问题),但我不太确定嵌套的异步返回调用会是什么样子,或者我如何传递基于事件的异步联系人搜索的结果返回到父调用方法- 我怎样才能达到这个效果?

I'm trying to write a method that grabs a contact, and converts it into a data object and returns it. I understand that since the contact search is asynchronous, the calling method needs to be also; however, I want to return an object as part of the parent method that's calling the search and I'm not quite sure what the best approach is.

The pseudocode I've got at the moment is:

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
}

I've done a bit of reading around the place (like this SO question) but I'm not quite sure how a nested asynchronous returning call would look like, or how I'd pass the result from the event based asynchronous contact search back onto the parent calling method - How would I achieve something to this effect?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦里的微风 2024-12-19 17:59:06

我稍微改变了你的代码。您需要在 GetRandomPersoncontacts_SearchCompleted 之间共享一个 Person 类。查看 contacts.SearchAsync 的参数,也许您可​​以将 myPerson 传递给它,而无需声明为类的私有字段。

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(); //*****
}

I changed your code a little bit. You need a shared class Person between GetRandomPerson and contacts_SearchCompleted. Look at the parameters of contacts.SearchAsync, Maybe you can pass myPerson to it without declaring as class'es private field.

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(); //*****
}
独享拥抱 2024-12-19 17:59:06

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

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

2) 将 GetRandomPerson 的调用(最初只是从 Button_Click 中调用)移至后台线程;在本例中,我使用了ThreadPool.QueueUserWorkItem。看来 UI 线程不能很好地从 WaitOne() 恢复,这是可以理解的。

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

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

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

Alright, I finally worked it out, and there were two parts to the solution:

1) Passing the DataObject I wanted created out of the result of the contacts search through as the third object state parameter in the .SearchAsync method call.

2) Moving the call for GetRandomPerson (which was originally just off a Button_Click) to a background thread; in this case I used ThreadPool.QueueUserWorkItem. It seems like the UI thread understandably doesn't recover very well from WaitOne().

If you're interested, the working code solution was:

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

I'm still interested in hearing if anyone has a more elegant solution to this, so please shout out if you've got one!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文