当另一个线程运行时,WPF动画停止
我有一个窗口,当另一个线程正在运行时显示一个“正在工作”的动画。窗口显示,我可以看到进度条,但动画已冻结。代码在ViewModel上运行,并在构造函数中创建dispatcher:当另一个线程运行时,WPF动画停止,wpf,animation,Wpf,Animation,我有一个窗口,当另一个线程正在运行时显示一个“正在工作”的动画。窗口显示,我可以看到进度条,但动画已冻结。代码在ViewModel上运行,并在构造函数中创建dispatcher: _dispatcher = Dispatcher.CurrentDispatcher; 创建动画并运行该过程的代码如下所示: Working wrk; protected void Search() { ImplementSearch(); wrk = new Working(); wrk.Ow
_dispatcher = Dispatcher.CurrentDispatcher;
创建动画并运行该过程的代码如下所示:
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();
}
我不明白为什么动画停止了?有人能帮忙吗?
谢谢您的线程没有做任何有用的事情-通过使用
\u dispatcher.BeginInvoke
运行搜索,您可以在UI线程上有效地执行搜索,从而阻止动画。从后台线程使用dispatcher仅用于操作UI控件或引发PropertyChanged事件的操作。我认为您希望在后台线程上执行实际工作,而不是将所有内容封送到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();
}
workingwrk;
受保护的无效搜索()
{
实现搜索();
wrk=新加工();
wrk.Owner=(MainWindow)App.Current.MainWindow;
wrk.WindowStartupLocation=WindowStartupLocation.CenterOwner;
wrk.HeadingMessage=“搜索…”;
wrk.UpdateMessage=“运行您的搜索”;
wrk.ShowDialog();
}
无效搜索()
{
线程=新线程(新线程开始(
代表()
{
//调用将UI-marshal更改为UI线程的函数。
_dispatcher.BeginInvoke((操作)(()=>ResetSearch());
string ret=_searchlogic.PerformSearch(SearchTerm,ref _matchingobjects,typeofilter());
如果(ret!=null)
{
//调用将UI-marshal更改为UI线程的函数。
_dispatcher.BeginInvoke((操作)((r)=>SearchMessage=r),ret);
}
如果(_matchingobjects.Count>0)
{
数据行;
foreach(在匹配对象中搜索逻辑匹配对象项)
{
行=_dt.NewRow();
行[“表”]=项.表;
行[“主键”]=item.pk;
_dt.行。添加(行);
}
//调用将UI-marshal更改为UI线程的函数。
_dispatcher.BeginInvoke((操作)(()=>SelectCurrent());
}
}
wrk.Close();
}));
thread.Start();
}
干杯!我已经成功地实现了这一点,尽管它引发了其他相关问题。具体来说,当搜索返回多个匹配对象时,不会填充_matchingobjects列表。这个列表是在UI线程中声明的,所以我想这就是问题所在。我还必须使用这个ObservableCollectionEx来防止异常。我将继续学习我对线程的基本理解!删除关于列表未被填充的注释通常,您可以在任何线程上访问非UI对象,但是您需要注意,多个线程不会同时尝试读取/写入它们。此外,线程间的操作不保证以任何顺序进行,这对于线程新手来说通常是错误的来源。Ok。这也许解释了我奇怪的新问题。当我运行一个只返回一次命中的搜索并且不需要datatable(_dt)时,一切都正常。如果我运行一个返回多条记录的搜索,它第一次工作,但是当我再次运行相同的搜索时,我得到一个错误{“位置0处没有行。”}。如果我一步一步地看代码,它似乎在工作,但当正常运行时,我会得到错误。这就好像数据表没有及时填充一样。有什么建议吗?尝试锁定对任何共享状态的访问。如果需要多个读卡器,可以使用lock
关键字(在封面下使用System.Threading.Monitor
),或使用类似System.Threading.ReaderWriterLockSlim
的内容。在这里可以看到一个关于同步的极好的视图:在该页面上向下滚动到“锁定和线程安全”并享受!但是,请注意,线程可能非常难以调试。如果您可以选择不共享状态,而是处理副本或返回值,这样会更好。