调用线程无法访问此对象,因为另一个线程拥有它。例外
The calling Thread cannot access this object because a different thread owns it. Exception
private void Thread1_Exe()
{
try
{
int sleepValT1 = Convert.ToInt32(listBoxT2.SelectedValue);
int StartLoop = 0;
int EndLoop = 10000;
for (int i = StartLoop; i <= EndLoop; i++)
{
Dispatcher.BeginInvoke(
new Action(() => listboxE1.Items.Add("T1: Execution Count> " + i.ToString())));
Thread.Sleep(sleepValT1);
}
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}
我试图在不同线程上调用上述函数
private void thread1_Click(object sender, RoutedEventArgs e)
{
threadBtn1.IsEnabled = false;
Thread t1 = new Thread(new ThreadStart(Thread1_Exe));
t1.Start();
}
但是当我 select 列表框中的值并尝试将其保存在变量中然后尝试将该值传递给
时会发生异常
Thread.Sleep()
我总是收到不同线程拥有此对象的异常。尝试了很多东西。请帮我解决我做错的地方。
谢谢
您的问题是您正在从后台线程访问 UI 控件。 UIs 往往是单线程的,因此您需要协调对控件的访问,以便它始终通过 UI 线程发生。
您可以做的最简单的事情是在启动新线程之前从列表框中读取值:
private void Thread1_Exe(int sleepVal)
{
try
{
int StartLoop = 0;
int EndLoop = 10000;
for (int i = StartLoop; i <= EndLoop; i++)
{
Dispatcher.BeginInvoke(
new Action(() =>
listboxE1.Items.Add("T1: Execution Count> " + i.ToString())));
Thread.Sleep(sleepVal);
}
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}
private void thread1_Click(object sender, RoutedEventArgs e)
{
threadBtn1.IsEnabled = false;
int sleepValT1 = Convert.ToInt32(listBoxT1.SelectedValue);
Thread t1 = new Thread(() => Thread1_Exe(sleepValT1));
t1.Start();
}
其他替代方法包括通过其调度程序线程访问控件:
private void Thread1_Exe()
{
try
{
int sleepValT1;
listBoxT1.Dispatcher.Invoke(() => sleepValT1 = Convert.ToInt32(listBoxT1.SelectedValue));
int StartLoop = 0;
int EndLoop = 10000;
for (int i = StartLoop; i <= EndLoop; i++)
{
Dispatcher.BeginInvoke(
new Action(() =>
listboxE1.Items.Add("T1: Execution Count> " + i.ToString())));
Thread.Sleep(sleepValT1);
}
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}
private void thread1_Click(object sender, RoutedEventArgs e)
{
threadBtn1.IsEnabled = false;
Thread t1 = new Thread(() => Thread1_Exe());
t1.Start();
}
通常,您真的希望尽可能避免在线程之间共享可变状态,以使事情更容易推理。
任何对 UI 元素的访问,无论是读还是写,都必须通过主 UI 线程调用。可以通过 Dispatcher
.
访问此线程
在你的代码中,我看到一行不是这种情况:当你调用 listBoxT2.SelectedValue
要修复错误,请在 Dispatcher
线程上调用此代码并将其保存到局部变量:
int selectedValue;
listBoxT2.Dispatcher.Invoke(() => selectedValue = Convert.ToInt32(listBoxT2.SelectedValue));
其余代码应该可以正常工作。
private void Thread1_Exe()
{
try
{
int sleepValT1 = Convert.ToInt32(listBoxT2.SelectedValue);
int StartLoop = 0;
int EndLoop = 10000;
for (int i = StartLoop; i <= EndLoop; i++)
{
Dispatcher.BeginInvoke(
new Action(() => listboxE1.Items.Add("T1: Execution Count> " + i.ToString())));
Thread.Sleep(sleepValT1);
}
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}
我试图在不同线程上调用上述函数
private void thread1_Click(object sender, RoutedEventArgs e)
{
threadBtn1.IsEnabled = false;
Thread t1 = new Thread(new ThreadStart(Thread1_Exe));
t1.Start();
}
但是当我 select 列表框中的值并尝试将其保存在变量中然后尝试将该值传递给
时会发生异常Thread.Sleep()
我总是收到不同线程拥有此对象的异常。尝试了很多东西。请帮我解决我做错的地方。
谢谢
您的问题是您正在从后台线程访问 UI 控件。 UIs 往往是单线程的,因此您需要协调对控件的访问,以便它始终通过 UI 线程发生。
您可以做的最简单的事情是在启动新线程之前从列表框中读取值:
private void Thread1_Exe(int sleepVal)
{
try
{
int StartLoop = 0;
int EndLoop = 10000;
for (int i = StartLoop; i <= EndLoop; i++)
{
Dispatcher.BeginInvoke(
new Action(() =>
listboxE1.Items.Add("T1: Execution Count> " + i.ToString())));
Thread.Sleep(sleepVal);
}
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}
private void thread1_Click(object sender, RoutedEventArgs e)
{
threadBtn1.IsEnabled = false;
int sleepValT1 = Convert.ToInt32(listBoxT1.SelectedValue);
Thread t1 = new Thread(() => Thread1_Exe(sleepValT1));
t1.Start();
}
其他替代方法包括通过其调度程序线程访问控件:
private void Thread1_Exe()
{
try
{
int sleepValT1;
listBoxT1.Dispatcher.Invoke(() => sleepValT1 = Convert.ToInt32(listBoxT1.SelectedValue));
int StartLoop = 0;
int EndLoop = 10000;
for (int i = StartLoop; i <= EndLoop; i++)
{
Dispatcher.BeginInvoke(
new Action(() =>
listboxE1.Items.Add("T1: Execution Count> " + i.ToString())));
Thread.Sleep(sleepValT1);
}
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}
private void thread1_Click(object sender, RoutedEventArgs e)
{
threadBtn1.IsEnabled = false;
Thread t1 = new Thread(() => Thread1_Exe());
t1.Start();
}
通常,您真的希望尽可能避免在线程之间共享可变状态,以使事情更容易推理。
任何对 UI 元素的访问,无论是读还是写,都必须通过主 UI 线程调用。可以通过 Dispatcher
.
在你的代码中,我看到一行不是这种情况:当你调用 listBoxT2.SelectedValue
要修复错误,请在 Dispatcher
线程上调用此代码并将其保存到局部变量:
int selectedValue;
listBoxT2.Dispatcher.Invoke(() => selectedValue = Convert.ToInt32(listBoxT2.SelectedValue));
其余代码应该可以正常工作。