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.

它是由我的网络服务客户端抛出的

以下是更新后的代码:

        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_DoWork内容都不应触及 UI 元素,也不应与 UI 元素数据绑定。如果您有一些返回数据,请将其打包成一个对象并将其填充到DoWorkEventArgs.Result属性中。
  3. 为该BackgroundWorker.RunWorkerCompleted事件添加另一个处理程序。此方法将在 UI 线程上运行,因此您可以从RunWorkerCompletedEventArgs(这将是您在 #2 中分配的结果对象)读取响应数据并根据需要更新 UI。

其美妙之BackgroundWorker处在于它将处理线程创建和将数据封送回 UI 线程——不需要任何东西Dispatcher.Invoke

更新

作为对您的编辑的响应,Web 服务调用可能会引发异常,但您得到的线程异常是由于尝试this从后台线程访问而引起的。

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

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

您将在RunWorkerCompleted处理程序中检查这些值,这就是您要显示MessageBox.

于 2012-10-05T01:51:45.130 回答