Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > WPF и Silverlight > BackgroundWorker - не всегда работает у меня : (


Автор: LectorSP 14.7.2008, 17:06
У меня такой вопрос, почему в обработчике события DoWork, я спокойно могу вызвать метод, который возвращает массив срок и передать его как результат работы нового потока , но не могу вызвать метод который создает и возвращает например TabItem? Как только в новом потоку появляеться строка типа TabItem item = new TabItem() поток возвращает ошибку типа "The calling thread must be STA, because many UI components require this." Подскажите или нужно делать через Thread? :

Автор: Partizan 14.7.2008, 17:32
LectorSP, ну а почему бы не сделать через Thread?

Автор: LectorSP 14.7.2008, 18:05
А как мен тогда из нового потока, который я создал, предать тот же TabItem, который сгенерился в новом потоке?

Автор: Partizan 14.7.2008, 18:15
LectorSP, через Invoke() делегата

Автор: LectorSP 14.7.2008, 18:25
а можно пару строчек код, если конечно не сложно : ) 

Автор: Partizan 14.7.2008, 18:27
Код

        private delegate void SetButton(Button btn);

        private void MySetButton(Button btn)
        {
            this.Controls.Add(btn);
            btn.Left = 0;
            btn.Top = 0;
            btn.Text = "Hello, World";
            btn.Show();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ThreadStart threadFunc = new ThreadStart(ThreadFunc);
            Thread thread = new Thread(threadFunc);
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }

        private void ThreadFunc()
        {
            Button btn = new Button();
            SetButton setBtnDelegate = new SetButton(MySetButton);
            this.Invoke(setBtnDelegate, btn);
        }

Автор: LectorSP 14.7.2008, 19:44
не рарботает постоянно выдает вот это Exception has been thrown by the target of an invocation : (

Автор: Partizan 14.7.2008, 19:45
LectorSP, показывайте свой код

Добавлено через 20 секунд
а лучше весь sln сюда для экспериментов...

Добавлено через 1 минуту и 24 секунды
LectorSP, Exception has been thrown by the target of an invocation как правило означает что исключение произошло в конструкторе при создании объекта

Автор: LectorSP 14.7.2008, 20:05
Этот пример тоже не работает : (

Код



public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private delegate void SetButton(Button btn);

        private void MySetButton(Button btn)
        {
            btn.Width = 100; // <- вылетает вот тут. Сам объект на null, однако все свойства помечены как [The calling thread cannot access this object because a different thread owns it.]
            btn.Height = 25;
            btn.Content = "Hello world";

            DockPanel.SetDock(btn, Dock.Top);

            dockPanel.Children.Add(btn);
           
        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            ThreadStart threadFunc = new ThreadStart(ThreadFunc);
            Thread thread = new Thread(threadFunc);
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }

        private void ThreadFunc()
        {
            Button btn = new Button();
            SetButton setBtnDelegate = new SetButton(MySetButton);
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, setBtnDelegate, btn);
        }

Автор: Partizan 14.7.2008, 20:10
LectorSP, я приводил пример для WinForms....
в вашем случае:

Код

public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
        private delegate void SetButton();
        private void MySetButton()
        {
            Button btn = new Button();
            btn.Width = 100; // <- вылетает вот тут. Сам объект на null, однако все свойства помечены как [The calling thread cannot access this object because a different thread owns it.]
            btn.Height = 25;
            btn.Content = "Hello world";
            DockPanel.SetDock(btn, Dock.Top);
            dockPanel.Children.Add(btn);
           
        }
        private void btnGo_Click(object sender, EventArgs e)
        {
            ThreadStart threadFunc = new ThreadStart(ThreadFunc);
            Thread thread = new Thread(threadFunc);
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }
        private void ThreadFunc()
        {
            SetButton setBtnDelegate = new SetButton(MySetButton);
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, setBtnDelegate, null);
        }

Автор: LectorSP 14.7.2008, 20:21
да, в моем случае WPF - и там почему-то так не работает : (

Автор: Partizan 14.7.2008, 20:22
LectorSP, =) вы Dispatcher не у того потока берёте )

Добавлено через 2 минуты и 37 секунд
хотя может я и не прав...

Добавлено через 8 минут и 27 секунд
LectorSP, 
Код

public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
        private delegate void SetButton();
        private void MySetButton()
        {
            Button btn = new Button();
            btn.Width = 100; // <- вылетает вот тут. Сам объект на null, однако все свойства помечены как [The calling thread cannot access this object because a different thread owns it.]
            btn.Height = 25;
            btn.Content = "Hello world";
            DockPanel.SetDock(btn, Dock.Top);
            dockPanel.Children.Add(btn);

        }
        private void btnGo_Click(object sender, EventArgs e)
        {

        }
        private void ThreadFunc()
        {
            SetButton setBtnDelegate = new SetButton(MySetButton);
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, setBtnDelegate);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            ThreadStart threadFunc = new ThreadStart(ThreadFunc);
            Thread thread = new Thread(threadFunc);
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }
    }


Автор: LectorSP 14.7.2008, 20:36
Дело в том, что если не передавать контрол, который сгенерил второй параллельный поток, а просто, во время выполнния этого потока получить доступ к контролам первого потока, то все работает отлично... А вот как сделать так, что бы передать контрол из одного потока в другой, не получаеться : (


Автор: Partizan 14.7.2008, 20:49
LectorSP, если контрол создан в одном из потоков, то он и принадлежит диспетчеру этого потока и никакому другому...

Автор: LectorSP 14.7.2008, 20:52
Вот тут ответ на вопрос, как это нужно делать используя WPF - http://www.nbdtech.com/blog/archive/2007/08/01/Passing-Wpf-Objects-Between-Threads-With-Source-Code.aspx  : )))

PS: Partizan, тебе огромное спасибо за то что потдержал меня в этом вопросе : )

Автор: Partizan 14.7.2008, 20:56
LectorSP, я в своё время читал эту статью....решение подходит не для всех задач + некоторое снижение быстродействия.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)