Загрузить WPF Combobox в отдельном потоке

Я пытаюсь загрузить в это поле со списком таблицу из базы данных, все работает нормально, но записей много, и загрузка занимает минуту. Я хотел бы переместить это в отдельный поток, но я продолжаю получать перекрестные потоки. Я думаю, что перекрестная потоковая передача происходит b / c, поле со списком находится в потоке пользовательского интерфейса. Кто-нибудь знает простой способ добиться этого.

Спасибо Майкл

private void BindComboBox()
{
        SqlConnection con = Program.GetConnection;
        SqlDataAdapter da = new SqlDataAdapter("SELECT ContactId, FullName FROM dbo.Contact WHERE FULLNAME IS NOT NULL", con);
        DataSet ds = new DataSet();
        da.Fill(ds, "dbo.Contact");

        SearchBOX.ItemsSource =  ds.Tables[0].DefaultView;
        SearchBOX.DisplayMemberPath = ds.Tables[0].Columns["FullName"].ToString();
        SearchBOX.SelectedValuePath = ds.Tables[0].Columns["ContactId"].ToString();
        SearchBOX.IsEnabled = true;
}

person perirose    schedule 04.06.2014    source источник
comment
Используйте Dispatcher.BeginInvoke для операций пользовательского интерфейса. Еще лучше, просто привяжите ItemsSource и обновите свойство поддержки в своем новом потоке.   -  person BradleyDotNET    schedule 04.06.2014
comment
боже спасибо, за ответ   -  person perirose    schedule 05.06.2014
comment
Может использовать фонового рабочего для загрузки данных в другой поток. Затем вы привязываете данные к элементу управления пользовательского интерфейса в полном событии. Только основной поток может получить доступ к элементу управления пользовательского интерфейса. Итак, что находится над пустой строкой, вы делаете в backgroundoworker.   -  person paparazzo    schedule 05.06.2014
comment
почему бы не использовать один из самых мощных аспектов WPF - привязку данных?   -  person mcy    schedule 05.06.2014


Ответы (2)


Попробуй это :

 Dispatcher.Invoke(new Action(() =>
    {
        // Your combo items loading code here
    }));
person HichemSeeSharp    schedule 04.06.2014

Упомяну возможные решения

  1. Dispatcher.Invoke для последовательного вызова или Dispatcher.BeginInvoke для асинхронного
  2. Новая тема от

    var thread = new Thread(new ThreadStart(delegate{ code to update }));
    

это не рекомендуется, поскольку для создания одного потока требуется много времени и памяти, вместо этого используйте этот

ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
                {

                }));

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

3. Еще один выход - BackgroundWorker. Он использует SynchronizationContext для переключения между обычным потоком и потоком пользовательского интерфейса.

        var worker = new BackgroundWorker();
        worker.DoWork += worker_DoWork;
        worker.WorkerReportsProgress = true;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.RunWorkerAsync();

Методы ProgressChanged и RunWorker завершили работу над потоком пользовательского интерфейса. Кстати, Backgroundworker использует ThreadPool. Потоки настроены как фоновые потоки (что означает, что при закрытии приложений потоки также будут закрыты). Избегайте замораживания потока в потоке пользовательского интерфейса. Подумайте о том, чтобы загружать не все в начале, а постепенно во время прокрутки вниз в списке.

person Maximus    schedule 04.06.2014