Вызывающий поток не может получить доступ к этому объекту, потому что другой поток владеет.В 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;
}
6 ответов
использовать диспетчер.Invoke метод.
выполняет указанный делегат синхронно в потоке Диспетчер связан с.
и
в WPF только поток, который создал DispatcherObject может получить доступ этот объект. Например,фоновый поток, который отключен от основной поток пользовательского интерфейса не может обновить содержимое кнопки, которая была создано в потоке пользовательского интерфейса. В заказать фоновый поток для доступ к свойству Content кнопки, фоновый поток должен делегируйте работу диспетчеру, связанному с потоком пользовательского интерфейса. Это достигается с помощью Invoke или BeginInvoke. Ссылаться на это синхронный и асинхронный метод BeginInvoke. Операция добавляется в очередь событий диспетчера в указанном DispatcherPriority.
вы получаете ошибку, потому что ваша метка создается в потоке пользовательского интерфейса, и вы пытаются изменить его содержимое с помощью другого потока. Здесь вам понадобится диспетчер.Взывать.
ознакомьтесь с этой статьей потоки WPF создают более отзывчивые приложения с помощью Диспетчера
для этого можно использовать Dispatcher. Ваш код становится...
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");
}
}
));
использовать диспетчер.Invoke
пример
void modi()
{
if(!Dispatcher.CheckAccess())
{
Dispatcher.Invoke(
()=>label1.Content = "df",DispatcherPriority.Normal);
}
else
{
label1.Content = "df";
}
}
Я начал один не-UI поток, и в этом потоке я тоже смотрел один поток UI. Поэтому мое требование похоже на запуск потока пользовательского интерфейса в потоке без пользовательского интерфейса. При обработке этого сценария я получил следующее исключение. "исключение: вызывающий поток не может получить доступ к этому объекту, потому что другой поток владеет."
в этом случае я использовал диспетчер.Вызовите метод элемента UI следующим образом, и он работал хорошо.
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;
}));
}
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");
}
}));
}
несколько предложений по использованию BeginInvoke, но без упоминания EndInvoke. Хорошая практика заключается в том, что "каждый BeginInvoke имеет соответствующий EndInvoke", и, конечно, должна быть какая-то защита от условий гонки (подумайте: что происходит с несколькими BeginInvoke кода, но никто еще не закончил обработку?)
легко забыть, и я видел эту ошибку (и, да, это is ошибка) как в примерах MSDN, так и в опубликованных книгах по WinForms