简体   繁体   中英

WPF animation not working

I'm trying to animate a loading screen while thread is working in background, but it won't work.

I realized that it has something to do with the backgroundworker calling Button.Dispatcher, however I can't remove it, because it would cause threading error. What should I do to fix this?

below is my code:

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

Update:

I remove UI calls from Do_Worker as suggested by Jay. Unfortunately I'm still getting an error:

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

It was thrown by my webservice client

below is the updated code:

        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);
            }
        }
  1. Your bg_DoWork method will already be running on a background thread, so no need to create a thread in there.
  2. Nothing in bg_DoWork should touch UI elements nor anything databound to UI elements. If you have some return data, package it up into an object and stuff it into the DoWorkEventArgs.Result property.
  3. Add another handler for the BackgroundWorker.RunWorkerCompleted event. This method will run back on the UI thread, so you can read your response data from the RunWorkerCompletedEventArgs (this will be the result object that you assigned in #2) and update the UI as necessary.

The beauty of BackgroundWorker is that it will handle thread creation and marshaling of data back to the UI thread -- no need for any Dispatcher.Invoke .

Update

In response to your edit, the web service call may be throwing an exception, but the thread exception you get is caused by trying to access this from a background thread.

Just as you'd have to package your success result in DoWorkEventArgs.Result , you'd need to package a failure result there too.

The object you pass back can be anything, so you can add things like a bool Success property, an Exception CaughtException property, etc.

You'll check these values in your RunWorkerCompleted handler and that is where you would show your MessageBox .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM