c# - 当我组合单击按钮和异步联系人调用时出现无限循环

标签 c# windows-phone-7 asynchronous contacts infinite-loop

当我将按钮单击事件与电话 (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;
    }

最佳答案

我最近遇到了类似的问题,我认为问题在于您在 button1_Click 中调用了 Thread.Sleep(),它在 UI 线程上运行不喜欢 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();
    }
}

请注意,这意味着您需要将按钮单击方法视为异步调用,因为您不知道后台线程何时会完成处理。

关于c# - 当我组合单击按钮和异步联系人调用时出现无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7701690/

相关文章:

c# - 使用 protobuf-net 反序列化字典

c# - 我使用 HttpClient 的 GET 请求循环陷入了 AggregateExceptions 的神秘困惑中

windows-phone-7 - WP7 中是否有标签控件?

javascript - 在 phonegap 和 Windows Phone 7 中使用 $.ajax 获取静态 html 文件

Windows Phone 7 开发 - 我需要服务提供商吗

java - 使用多个线程仅调用一次方法

jquery - 使用jquery.form.js的异步上传问题

c# - 具有水平和垂直卡住 Pane 的 Gridview

android - 如何将 ExecutorService 与 Android AsyncTask 一起使用?

c# - Log4Net 记录到特定 Appender .NET Core