WPF动画无效

时间:2012-10-05 01:32:38

标签: c# wpf wcf animation

我正在尝试在线程在后台运行时为加载屏幕制作动画,但它不起作用。

我意识到它与调用Button.Dispatcher的backgroundworker有关,但是我无法删除它,因为它会导致线程错误。我该怎么做才能解决这个问题?

下面是我的代码:

        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.

我的网络服务客户端

抛出了它

下面是更新的代码:

        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 个答案:

答案 0 :(得分:1)

  1. 您的bg_DoWork方法已经在后台线程上运行,因此无需在其中创建线程。
  2. bg_DoWork中的任何内容都不应触及UI元素或任何数据绑定到UI元素。如果您有一些返回数据,请将其打包到一个对象中并将其填入DoWorkEventArgs.Result属性。
  3. BackgroundWorker.RunWorkerCompleted事件添加另一个处理程序。此方法将在UI线程上运行,因此您可以从RunWorkerCompletedEventArgs读取响应数据(这将是您在#2中指定的结果对象)并根据需要更新UI。
  4. BackgroundWorker的美妙之处在于它将处理线程创建和数据封送回UI线程 - 不需要任何Dispatcher.Invoke

    更新

    为了响应您的编辑,Web服务调用可能会抛出异常,但是您获得的线程异常是由尝试从后台线程访问this引起的。

    正如您必须将成功结果打包在DoWorkEventArgs.Result中一样,您也需要在此处打包失败结果。

    您传回的对象可以是任何内容,因此您可以添加bool Success属性,Exception CaughtException属性,等内容。

    您将在RunWorkerCompleted处理程序中检查这些值,这是您展示MessageBox的位置。