2010-07-01 159 views
1

当另一个线程运行时,我有一个窗口显示'工作'动画。窗口显示,我可以看到进度条,但动画被冻结。该代码运行在一个视图模型,并在构造函数中创建调度:当另一个线程运行时,WPF动画停止运行

​​

创建动画和运行过程的代码如下:

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

我想不出为什么动画停止?谁能帮忙? 谢谢

回答

2

我认为你想在后台线程上做实际的工作,而不是将所有事情都封送到UI线程,这就是BeginInvoke所做的!通过使用BeginInvoke在UI线程上执行所有操作,您的动画将不会运行。

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(); 
} 
+0

干杯!我已经取得了一些成功,虽然它抛出了其他相关的问题。具体而言,当搜索返回多个匹配对象时,不会填充_matchingobjects列表。这个列表是在UI线程中声明的,所以我想这就是问题所在。我也必须使用这个ObservableCollectionEx http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx来防止异常。将士兵与我的基本理解线程! – pilsdumps 2010-07-02 08:09:26

+0

从头开始评论有关未被填充的列表 – pilsdumps 2010-07-02 08:17:19

+0

通常,您可以访问任何线程上的_non-UI_对象,但是您需要注意多个线程不会同时读取/写入它们。此外,线程间的操作并不保证以任何顺序进行,这通常是新手进行线程处理的错误来源。 – codekaizen 2010-07-02 08:53:59

0

您的线程没有任何用处 - 通过使用_dispatcher.BeginInvoke来运行搜索,您将有效地在UI线程上执行搜索,从而阻止您的动画。仅将后台线程的调度程序用于操作UI控件或引发PropertyChanged事件的操作。