WPF使用和访问BackgroundWorker线程中的ObjectContext

时间:2020-11-30 09:22:24

I have a code like the following (I have stripped some code for readability)

我有一个像下面这样的代码(为了便于阅读,我删除了一些代码)

    private void RicercaArticoloStripped(object sender, DoWorkEventArgs e)
    {
        try
        {
            using (var context = new ControlloSchedeLocalEntities())
            {
                var prodotti = context.VProdotti.Where(i => i.WACMAT == textBoxCodiceArticolo.Text);

                if (prodotti.Count() > 0)
                {
                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                    {
                        textBlockDescrizioneArticolo.Text = prodotti.FirstOrDefault().WADESC;
                    }));
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error:\n\n" + ex.Message + "\r\nStack: " + ex.ToString());
        }
    }


    private void textBoxCodiceArticolo_KeyUpStripped(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.DoWork += new DoWorkEventHandler(RicercaArticoloStripped);
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RicercaArticoloWorkerCompleted);
            worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);

            object[] parameters = new object[] { textBoxCodiceArticolo.Text, textBlockDescrizioneArticolo.Text };
            worker.RunWorkerAsync(parameters);
        }
    }

So, as for my understanding of BackgroundWorker, when I instantiate the: var prodotti = context.VProdotti.Where(i => i.WACMAT == textBoxCodiceArticolo.Text);

所以,至于我对BackgroundWorker的理解,当我实例化:var prodotti = context.VProdotti.Where(i => i.WACMAT == textBoxCodiceArticolo.Text);

I am doing it FROM the working thread, not the UI thread.

我是从工作线程而不是UI线程做的。

But I get an exception on the line immediately below, when I try to access the value: if (prodotti.Count() > 0)

但是当我尝试访问该值时,我在下面的行上得到一个例外:if(prodotti.Count()> 0)

I get the (in)famous error: "The calling thread cannot access this object because a different thread owns it"

我得到(in)着名的错误:“调用线程无法访问此对象,因为另一个线程拥有它”

Why?

2 个解决方案

#1


0  

As you already said you must use Dispatcher.BeginInvoke/Invoke to perform operations from the control's owner thread or you will get "The calling thread cannot access this object because a different thread owns it" exception. Thats why you got this exception;

正如您已经说过的那样,您必须使用Dispatcher.BeginInvoke / Invoke来从控件的所有者线程执行操作,否则您将得到“调用线程无法访问此对象,因为不同的线程拥有它”异常。这就是为什么你得到这个例外;

And here is why you got this exception on the line below (when prodotti.Count() was called):

这就是为什么你在下面这一行得到这个例外的原因(当调用prodotti.Count()时):

When you create prodotti variable it's just a IEnumerable<T> object. So he actually calculates only when you call for prodotti.Count() method and thats why you got exception on this line.

当你创建prodotti变量时,它只是一个IEnumerable 对象。所以他实际上只在你调用prodotti.Count()方法时进行计算,这就是为什么你在这一行上有异常的原因。

IEnumerable actually is generator, that means that he will produce new set of objects every time he used.

IEnumerable实际上是生成器,这意味着他每次使用时都会生成新的对象集。

To test this you can calculate prodotti as shown bellow:

要测试这个,您可以计算prodotti,如下所示:

var prodotti = context.VProdotti.Where(i => i.WACMAT == textBoxCodiceArticolo.Text).ToList();

In this case you will get exception immediately because .ToList() forces all calculations.

在这种情况下,您将立即获得异常,因为.ToList()强制进行所有计算。

Check this article for generators and enumerators: http://www.codeproject.com/Articles/155462/IEnumerable-Lazy-and-Dangerous

查看本文的发电机和调查员:http://www.codeproject.com/Articles/155462/IEnumerable-Lazy-and-Dangerous

Updated: really, when you use IEnumerable with reference types you can get the same objects as previously. Read this answer for more: https://*.com/a/14361094/1467309

更新:实际上,当您使用IEnumerable与引用类型时,您可以获得与以前相同的对象。请阅读此答案以获取更多信息:https://*.com/a/14361094/1467309

#2


0  

The property Text of TextBox gets the value of the DependencyProperty Text, this can only be done from the UI-thread. You are accessing textBoxCodiceArticolo.Text from your Worker thread.

Text of TextBox属性获取DependencyProperty Text的值,这只能从UI线程完成。您正在从Worker线程访问textBoxCodiceArticolo.Text。

#1


0  

As you already said you must use Dispatcher.BeginInvoke/Invoke to perform operations from the control's owner thread or you will get "The calling thread cannot access this object because a different thread owns it" exception. Thats why you got this exception;

正如您已经说过的那样,您必须使用Dispatcher.BeginInvoke / Invoke来从控件的所有者线程执行操作,否则您将得到“调用线程无法访问此对象,因为不同的线程拥有它”异常。这就是为什么你得到这个例外;

And here is why you got this exception on the line below (when prodotti.Count() was called):

这就是为什么你在下面这一行得到这个例外的原因(当调用prodotti.Count()时):

When you create prodotti variable it's just a IEnumerable<T> object. So he actually calculates only when you call for prodotti.Count() method and thats why you got exception on this line.

当你创建prodotti变量时,它只是一个IEnumerable 对象。所以他实际上只在你调用prodotti.Count()方法时进行计算,这就是为什么你在这一行上有异常的原因。

IEnumerable actually is generator, that means that he will produce new set of objects every time he used.

IEnumerable实际上是生成器,这意味着他每次使用时都会生成新的对象集。

To test this you can calculate prodotti as shown bellow:

要测试这个,您可以计算prodotti,如下所示:

var prodotti = context.VProdotti.Where(i => i.WACMAT == textBoxCodiceArticolo.Text).ToList();

In this case you will get exception immediately because .ToList() forces all calculations.

在这种情况下,您将立即获得异常,因为.ToList()强制进行所有计算。

Check this article for generators and enumerators: http://www.codeproject.com/Articles/155462/IEnumerable-Lazy-and-Dangerous

查看本文的发电机和调查员:http://www.codeproject.com/Articles/155462/IEnumerable-Lazy-and-Dangerous

Updated: really, when you use IEnumerable with reference types you can get the same objects as previously. Read this answer for more: https://*.com/a/14361094/1467309

更新:实际上,当您使用IEnumerable与引用类型时,您可以获得与以前相同的对象。请阅读此答案以获取更多信息:https://*.com/a/14361094/1467309

#2


0  

The property Text of TextBox gets the value of the DependencyProperty Text, this can only be done from the UI-thread. You are accessing textBoxCodiceArticolo.Text from your Worker thread.

Text of TextBox属性获取DependencyProperty Text的值,这只能从UI线程完成。您正在从Worker线程访问textBoxCodiceArticolo.Text。