WPF animation stops when another thread running

2019-02-20 06:05发布

问题:

I've a window that shows a 'working' animation when another thread is running. The window shows and I can see the progress bar but the animation is frozen. The code runs on a ViewModel, and the dispatcher is created in the constructor:

_dispatcher = Dispatcher.CurrentDispatcher;

The code to create the animation and run the process is as follows:

Working wrk;    
protected void Search()
{
  ImplementSearch();

  wrk = new Working();
  wrk.Owner = (MainWindow)App.Current.MainWindow;
  wrk.WindowStartupLocation = WindowStartupLocation.CenterOwner;
  wrk.HeadingMessage = "Searching...";
  wrk.UpdateMessage = "Running your search";
  wrk.ShowDialog();      
}

void ImplementSearch()
{
  System.Threading.Thread thread = new System.Threading.Thread(
    new System.Threading.ThreadStart(
      delegate()
      {
        System.Windows.Threading.DispatcherOperation
          dispatcherOp = _dispatcher.BeginInvoke(
          System.Windows.Threading.DispatcherPriority.Normal,
          new Action(
            delegate()
            {                  
              ResetSearch();

              string ret = _searchlogic.PerformSearch(SearchTerm, ref _matchingobjects, TypeOfFilter());
              if (ret != null)
                SearchMessage = ret;

              if (_matchingobjects.Count > 0)
              {
                DataRow row;
                foreach (SearchLogicMatchingObjects item in _matchingobjects)
                {
                  row = _dt.NewRow();
                  row["table"] = item.Table;
                  row["pk"] = item.PK;
                  _dt.Rows.Add(row);
                }

                SelectCurrent();
              }          
            }
        ));

        dispatcherOp.Completed += new EventHandler(dispatcherOp_Completed);
      }
  ));

  thread.Start();
}

void dispatcherOp_Completed(object sender, EventArgs e)
{
  wrk.Close();
}

I can't figure out why the animation stops? Can anyone help? Thanks

回答1:

I think you want to do the actual work on the background thread, not marshal everything to the UI thread, which is what BeginInvoke does! By doing everything on the UI thread with BeginInvoke, your animation won't run.

Working wrk;     
protected void Search() 
{ 
  ImplementSearch(); 

  wrk = new Working(); 
  wrk.Owner = (MainWindow)App.Current.MainWindow; 
  wrk.WindowStartupLocation = WindowStartupLocation.CenterOwner; 
  wrk.HeadingMessage = "Searching..."; 
  wrk.UpdateMessage = "Running your search"; 
  wrk.ShowDialog();       
} 

void ImplementSearch() 
{ 
    Thread thread = new Thread(new ThreadStart( 
      delegate() 
      { 
          // Call to function which changes UI - marshal to UI thread.
          _dispatcher.BeginInvoke((Action)(() => ResetSearch()));

          string ret = _searchlogic.PerformSearch(SearchTerm, ref _matchingobjects, TypeOfFilter()); 

          if (ret != null) 
          {
              // Call to function which changes UI - marshal to UI thread.
              _dispatcher.BeginInvoke((Action<string>)((r) => SearchMessage = r), ret);
          }

          if (_matchingobjects.Count > 0) 
          { 
            DataRow row; 
            foreach (SearchLogicMatchingObjects item in _matchingobjects) 
            { 
              row = _dt.NewRow(); 
              row["table"] = item.Table; 
              row["pk"] = item.PK; 
              _dt.Rows.Add(row); 
            }  

            // Call to function which changes UI - marshal to UI thread.
            _dispatcher.BeginInvoke((Action)(() => SelectCurrent()));
          }           
        } 

        wrk.Close();
  })); 
  thread.Start();
} 


回答2:

Your thread does nothing useful - by using _dispatcher.BeginInvoke to run your search you are effectively executing the search on the UI thread, which blocks your animation. Use dispatcher from your background thread only for operations that manipulate UI controls or that cause PropertyChanged events to be fired.



标签: wpf animation