Как я могу передать результат асинхронного поиска контактов обратно в вызывающий метод? - PullRequest
0 голосов
/ 29 октября 2011

Я пытаюсь написать метод, который захватывает контакт, преобразует его в объект данных и возвращает его. Я понимаю, что поскольку поиск контактов является асинхронным, вызывающий метод также должен быть; тем не менее, я хочу вернуть объект как часть родительского метода, который вызывает поиск, и я не совсем уверен, что лучший подход.

Псевдокод, который у меня есть на данный момент:

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
}

Я немного почитал ( как этот вопрос ), но я не совсем уверен, как будет выглядеть вложенный асинхронный ответный вызов или как я передам результат асинхронного поиска контактов на основе событий обратно в родительский вызывающий метод - Как бы я чего-то достиг?

Ответы [ 2 ]

1 голос
/ 29 октября 2011

Я немного изменил твой код. Вам нужен общий класс Person между GetRandomPerson и contacts_SearchCompleted. Посмотрите на параметры 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(); //*****
}
0 голосов
/ 30 октября 2011

Хорошо, я наконец-то решил это, и решение было разделено на две части:

1) Передача объекта DataObject, который я хотел создать, в результате поиска контактов через третий параметр состояния объекта ввызов метода .SearchAsync.

2) Перемещение вызова для GetRandomPerson (который изначально был только Button_Click) в фоновый поток;в этом случае я использовал ThreadPool.QueueUserWorkItem .Похоже, что поток пользовательского интерфейса по понятным причинам не очень хорошо восстанавливается из 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();
    }
}

Мне все еще интересно услышать, есть ли у кого-нибудь более изящное решение для этого, поэтому, пожалуйста, кричите, если у вас есть такое!

...