1

我有如下代码(为了便于阅读,我删除了一些代码)

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

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

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

但是当我尝试访问该值时,下面的行出现异常: if (prodotti.Count() > 0)

我得到了一个著名的错误: “调用线程无法访问这个对象,因为另一个线程拥有它”

为什么?

4

2 回答 2

0

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

于 2013-01-16T14:05:54.433 回答
0

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

这就是为什么您在下面的行(何时prodotti.Count()调用)出现此异常:

当您创建prodotti变量时,它只是一个IEnumerable<T>对象。所以他实际上只在你调用prodotti.Count()方法时计算,这就是你在这条线上遇到异常的原因。

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

要对此进行测试,您可以计算prodotti如下所示:

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

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

检查这篇文章的生成器和枚举器:http: //www.codeproject.com/Articles/155462/IEnumerable-Lazy-and-Dangerous

更新:真的,当您使用带有引用类型的 IEnumerable 时,您可以获得与以前相同的对象。阅读此答案了解更多信息:https ://stackoverflow.com/a/14361094/1467309

于 2013-01-16T13:56:57.043 回答