我正在尝试在单独的线程中运行for循环,以便UI应该响应并且进度条可见。
问题是我不知道该怎么做:)。在此代码中,进程在单独的线程中启动,但代码的下一部分同时执行。将显示messageBox并且永远不会返回结果(例如,从不设置列表框的选定索引属性)。
即使我使用“taskEx.delay()”也无效。
TaskEx.Run(() =>
{
for (int i = 0; i < sResults.Count(); i++)
{
if (sResults.ElementAt(i).DisplayIndexForSearchListBox.Trim().Contains(ayaStr))
{
lstGoto.SelectedIndex = i;
lstGoto_SelectionChanged(lstReadingSearchResults, null);
IsIndexMatched = true;
break;
}
}
});
//TaskEx.delay(1000);
if (IsIndexMatched == true)
stkPanelGoto.Visibility = Visibility.Collapsed;
else //the index didn't match
{
MessagePrompt.ShowMessage("The test'" + ayaStr + "' does not exist.", "Warning!");
}
有谁能告诉我如何使用带有“for”或“foreach”循环的多线程?
答案 0 :(得分:5)
您需要使用Task.Wait()
试试这个:
TaskEx.Wait();
if (IsIndexMatched == true)
stkPanelGoto.Visibility = Visibility.Collapsed;
如果您想限制等待时间,可以提供Wait()
时间参数或TimeSpan,例如:
TaskEx.Wait(10000)
您也可以将其与CancellationToken,
一起使用
或者CancellationToken和时间限制的组合
了解MSDN上的所有选项:
http://msdn.microsoft.com/en-us/library/dd235635.aspx
答案 1 :(得分:2)
TaskEx
- 你在使用.NET 4.0的异步定位包吗?
在这种情况下,使用await TaskEx.Run(...)
- C#5.0 await
将等到任务完成,但会在等待时保持UI响应(与.Wait()
方法不同)。
此外,您需要将lstGoto.SelectedIndex = i;
分配移出后台线程 - 只允许在主线程上访问UI控件。
int index = await TaskEx.Run(() =>
{
// ensure that sResults is a List<T> - call .ToList() if necessary
for (int i = 0; i < sResults.Count; i++)
{
if (sResults[i].DisplayIndexForSearchListBox.Trim().Contains(ayaStr))
{
return i;
}
}
return -1; // nothing found
});
//await TaskEx.Delay(1000);
if (index >= 0)
{
stkPanelGoto.Visibility = Visibility.Collapsed;
lstGoto.SelectedIndex = i;
lstGoto_SelectionChanged(lstReadingSearchResults, null);
}
else //the index didn't match
{
MessagePrompt.ShowMessage("The test'" + ayaStr + "' does not exist.", "Warning!");
}
警告的最后一句话:不要在循环中反复使用Count()
/ ElementAt()
- 这些LINQ方法可能最终遍历整个集合以计算其结果。如果你需要通过索引遍历IEnumerable,那么将它转换为List一次然后遍历列表要快得多。
答案 2 :(得分:2)
应用修复后的代码。
int index = -1;
IEnumerable<dictSearchResults> sResults = (IEnumerable<dictSearchResults>)lstGoto.DataContext;
//Makin a list of all the DisplayIndex from the IEnumerable object
var lstGotoResults= sResults.Select(rec => rec.DisplayIndexForSearchListBox.ToString()).ToList();
index = await TaskEx.Run(() =>
{
return lstGotoResults.IndexOf(ayaIndexStr);
});
if (index >= 0)
{
lstGoto.SelectedIndex = index ;
lstGoto_SelectionChanged(lstReadingSearchResults, null);
stkPanelGoto.Visibility = Visibility.Collapsed;
}
将IEnumerable转换为List后,代码非常有效,我怀疑是否应该使用TaskEx
。进度条没有时间可见:)
谢谢丹尼尔的提示!