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
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
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。