0

スレッドがバックグラウンドで動作しているときにロード画面をアニメーション化しようとしていますが、うまくいきません。

Button.Dispatcher を呼び出すバックグラウンド ワーカーと関係があることに気付きましたが、スレッド エラーが発生するため削除できません。これを修正するにはどうすればよいですか?

以下は私のコードです:

        private void btnLogin_Click(object sender, RoutedEventArgs e)
        {
            Storyboard sb = (Storyboard)FindResource("Loading");
            sb.Dispatcher.BeginInvoke(new Action(() => sb.Begin()), DispatcherPriority.Normal, null);

            BackgroundWorker bg = new BackgroundWorker();
            bg.DoWork += new DoWorkEventHandler(bg_DoWork);
            bg.RunWorkerAsync();
        }

        private void bg_DoWork(object sender, DoWorkEventArgs e)
        {
            System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(RunThread));
            thread.Start();            
        }

        private void RunThread()
        {
            btnLogin.Dispatcher.BeginInvoke(new Action(() => TheBackgroundWork()), DispatcherPriority.Normal, null);
        }

アップデート:

Jay の提案に従って、Do_Worker から UI 呼び出しを削除します。残念ながら、私はまだエラーが発生しています:

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

Webサービスクライアントによってスローされました

以下は更新されたコードです。

        private WebServiceClient proxy = new WebServiceClient();

        private void btnLogin_Click(object sender, RoutedEventArgs e)
        {
            sb = (Storyboard)FindResource("sbLoading");
            sb.Dispatcher.BeginInvoke(new Action(() => sb.Begin()), DispatcherPriority.Normal, null);

            BackgroundWorker bg = new BackgroundWorker();
            bg.DoWork += new DoWorkEventHandler(bg_DoWork);
            bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
            bg.RunWorkerAsync();
        }

        private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var u = e.Result;
            if (u != null)
                //pass the data
        }

        private void bg_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                var u = proxy.ToWebService(x,y); //this guy throws an error
                e.Result = u;
            }
            catch
            {
                this.Dispatcher.Invoke(new Action(
                    () => MessageBox.Show("Connection Error", this.Title)), 
                    DispatcherPriority.Normal, null);
            }
        }
4

1 に答える 1

1
  1. bg_DoWorkメソッドはすでにバックグラウンドスレッドで実行されているため、そこにスレッドを作成する必要はありません。
  2. bg_DoWorkUI要素に触れたり、UI要素にデータバインドされたものに触れたりすることはできません。戻りデータがある場合は、それをオブジェクトにパッケージ化し、DoWorkEventArgs.Resultプロパティに詰め込みます。
  3. イベントの別のハンドラーを追加しBackgroundWorker.RunWorkerCompletedます。このメソッドはUIスレッドで実行されるため、(これは#2で割り当てた結果オブジェクトになります)から応答データを読み取り、RunWorkerCompletedEventArgs必要に応じてUIを更新できます。

BackgroundWorker利点は、スレッドの作成とUIスレッドへのデータのマーシャリングを処理することです。これは必要ありませんDispatcher.Invoke

アップデート

編集に応じて、Webサービス呼び出しが例外をスローしている可能性がありますが、発生するスレッド例外はthis、バックグラウンドスレッドからアクセスしようとしたことが原因です。

成功結果をにパッケージ化する必要があるのと同じようにDoWorkEventArgs.Result、失敗結果もそこにパッケージ化する必要があります。

返すオブジェクトは何でもかまいません。そのため、bool SuccessプロパティやException CaughtExceptionプロパティなどを追加できます。

ハンドラーでこれらの値を確認し、RunWorkerCompletedそこにを表示しますMessageBox

于 2012-10-05T01:51:45.130 に答える