Подтвердить что ты не робот

Вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит другой поток. WPF

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

delegate void lostfocs(string st);
   private void imgPayment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {

        Thread t = new Thread(modi);
        t.Start();
    }
 void modi()
    {
        try
        {
            label1.Content = "df";
        }
        catch
        {
            lostfocs ld = new lostfocs(up);
          //  ld.Invoke("df");
            object obj=new object();
            ld.Invoke("sdaf");
        }
    }
void up(string st)
    {
        label1.Content = st;
    }
4b9b3361

Ответ 1

Использовать метод Dispatcher.Invoke.

Выполняет указанный делегат синхронно в потоке Диспетчер связан с.

Кроме

В WPF доступен только поток, создавший объект DispatcherObject этот объект. Например, фоновый поток, который выделяется из основной поток пользовательского интерфейса не может обновлять содержимое кнопки, которая была созданный в потоке пользовательского интерфейса. Для того чтобы фоновый поток доступ к свойству Content Button, фоновый поток должен делегировать работу диспетчеру, связанному с потоком пользовательского интерфейса. Это достигается с помощью Invoke или BeginInvoke. Вызов синхронный, а BeginInvoke - асинхронный. Операция добавляется к очередь событий Диспетчера в указанном DispatcherPriority.

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

Ознакомьтесь с этой статьей WPF Threads создают более адаптивные приложения с Диспетчером

Ответ 2

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

private void imgPayment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Dispatcher.BeginInvoke(DispatcherPriority.Input, new ThreadStart(() =>
    {
        try
        {
            label1.Content = "df";
        }
        catch
        {
            lostfocs ld = new lostfocs(up);
          //  ld.Invoke("df");
            object obj=new object();
            ld.Invoke("sdaf");
        }
    }
));

Ответ 3

использовать Dispatcher.Invoke

Пример

    void modi()
    {
        if(!Dispatcher.CheckAccess())
        {
            Dispatcher.Invoke(
                    ()=>label1.Content = "df",DispatcherPriority.Normal);
        }
        else
        {
            label1.Content = "df";
        }
    }

Ответ 4

Я начал один поток, не связанный с UI, и в этом потоке я тоже смотрел один поток пользовательского интерфейса. Поэтому мое требование подобно запуску потока пользовательского интерфейса в потоке, отличном от UI. При обработке этого сценария я получил следующее исключение. "Исключение: вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит другой поток.

В этом случае я использовал метод Dispatcher.Invoke элемента пользовательского интерфейса следующим образом, и он работал хорошо.

if (m_contextWindow == null)
{   
    System.Threading.Thread newWindowThread = new System.Threading.Thread(new ThreadStart( () =>
    {
        // Create and show the Window
        m_contextWindow = new ContextWindow();
        m_contextWindow.DataContext = this;                            
        m_contextWindow.Show();
        // Start the Dispatcher Processing
        System.Windows.Threading.Dispatcher.Run();
    }));

    // Set the apartment state
    newWindowThread.SetApartmentState(ApartmentState.STA);
    // Make the thread a background thread
    newWindowThread.IsBackground = true;
    // Start the thread
    newWindowThread.Start();
}
else
{                     
    this.m_contextWindow.Dispatcher.Invoke(new ThreadStart(() => 
    {
        m_contextWindow.DataContext = this;
        if (m_contextWindow.Visibility == System.Windows.Visibility.Collapsed
         || m_contextWindow.Visibility == System.Windows.Visibility.Hidden)
            m_contextWindow.Visibility = System.Windows.Visibility.Visible;
    }));                            
}

Ответ 5

private void imgPayment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Input, new ThreadStart(() =>
            {
                try
                {
                    label1.Content = "df";
                }
                catch
                {
                    lostfocs ld = new lostfocs(up);
                    object obj = new object();
                    ld.Invoke("sdaf");
                }
            }));
        }

Ответ 6

Несколько советов по использованию BeginInvoke, но не упоминание EndInvoke. Хорошая практика заключается в том, что "у каждого BeginInvoke есть соответствующий EndInvoke" и, конечно же, должна быть какая-то защита от условий гонки (подумайте: что происходит с несколькими BeginInvoke кода, но никто еще не завершил обработку?)

Легко забыть, и я видел эту ошибку (и, да, это ошибка) как в примерах MSDN, так и в опубликованных книгах по WinForms