The calling Thread cannot access this object because a different thread owns it. Exception

生来就可爱ヽ(ⅴ<●) 提交于 2021-02-10 23:34:58

问题


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);
    }
}

I was trying to call the above function on different thread

private void thread1_Click(object sender, RoutedEventArgs e)
{
    threadBtn1.IsEnabled = false;
    Thread t1 = new Thread(new ThreadStart(Thread1_Exe));

    t1.Start();
}

But the Exception occurs when i select the value from the listbox and try to save it in the variable and then try to pass that value in

Thread.Sleep()

I always get this Exception that the different thread owns this object. Tried Many things. Please help me out where i am doing mistake.

Thanks


回答1:


Your problem is that you are accessing a UI control from a background thread. UIs tend to be single-threaded, so you need to coordinate access to the controls so that it always happens via the UI thread.

The simplest thing you can do is read the value from your listbox before firing up the new thread:

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();
}

Other alternatives include accessing the control via its dispatcher thread:

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();
}

Generally, you really want to avoid sharing mutable state between threads as much as possible, to keep things easier to reason about.




回答2:


Any access to a UI element, no matter if it is read or write, must be called through main UI thread. This thread is accessible through the Dispatcher.

In your code I see a line where this is not the case: when you are calling listBoxT2.SelectedValue

To fix the error call this code on the Dispatcher Thread and save it to a local variable:

int selectedValue;
listBoxT2.Dispatcher.Invoke(() => selectedValue = Convert.ToInt32(listBoxT2.SelectedValue));
   

The rest of the code should work fine.



来源:https://stackoverflow.com/questions/35459876/the-calling-thread-cannot-access-this-object-because-a-different-thread-owns-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!