Бесконечный цикл, когда я объединяю нажатие кнопки и асинхронный вызов контактов - PullRequest
2 голосов
/ 09 октября 2011

У меня проблема, когда я объединяю событие нажатия кнопки с асинхронным вызовом контактов на телефоне (WP7).Проблема заключается в том, что событие SearchCompleted для вызова асинхронных контактов не запускается до завершения события Click.Это приведет к бесконечному циклу в ожидании завершения асинхронного вызова.

В моем примере с упрощенным кодом у меня есть флажок и кнопка.Когда кнопка нажата, возникает событие щелчка.Если флажок установлен, то для получения всех контактов на телефоне будет выполняться асинхронный вызов SearchAsync.

Как избежать бесконечного цикла, в результате которого этот код будет вызываться, если флажок установлен:

    private bool searchCompleted = false;
    private Contact[] contacts;

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Dictionary<int, string> contactList = new Dictionary<int,string>;

        // ... add contacts to the contactList ...
        contactList.Add(1, "a contact name");

        // if CheckBox is checked add contacts from the phone Contacts
        if (checkBoxContacts.IsChecked == true)
        {
            Contacts cons = new Contacts();

            cons.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(Contacts_SearchCompleted);
            cons.SearchAsync(string.Empty, FilterKind.None, null);

            searchCompleted = false;
            while (!searchCompleted) 
            {
                Thread.Sleep(100);
            }
            int n = 1;
            foreach (Contact contact in contacts)
            {
                contactList.Add(n, contact.DisplayName);
            }
        }

        // .... add more namnes to the contactList from other places....

        // .... do something with the contactList ....

        // Navigate to the next dialog 
        NavigationService.Navigate(new Uri("/NextPage.xaml", UriKind.Relative));
    }

    private void Contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
    {
        contacts = e.Results.ToArray();
        searchCompleted = true;
    }

Ответы [ 3 ]

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

У меня недавно была похожая проблема, и я думаю, что проблема в том, что вы вызываете Thread.Sleep () в пределах button1_Click , который работает в потоке пользовательского интерфейса, который не ' любезно относитесь к Thread.Sleep () или .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();
    }
}

Обратите внимание, что это означает, что вам нужно будет рассматривать ваш метод нажатия кнопки как асинхронный вызов, поскольку вы не знаете, когда фоновый поток завершит обработку.

0 голосов
/ 09 октября 2011

Сколько времени занимает поиск?Если у вас очень мало контактов или их нет, поиск может завершиться до того, как вы выполните

searchComplete = false;

В этом случае ваш цикл никогда не закончится, так как searchComplete никогда не будет установлен наtrue.

0 голосов
/ 09 октября 2011

Удалить бесконечный цикл и переместить код для заполнения contatList в обработчик событий

 private void Contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
    {
      contacts = e.Results.ToArray();
      int n = 1;
      foreach (Contact contact in contacts)
      {
        contactList.Add(n, contact.DisplayName);
      }
    }
...