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

のプロパティTextTextBoxの値を取得しますDependencyProperty Text。これはUIスレッドからのみ実行できます。textBoxCodiceArticolo.Textワーカースレッドからアクセスしています。

于 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 に答える