如何使用带有“for”或“foreach”循环的多线程?

时间:2012-07-01 08:50:44

标签: c# .net multithreading asynchronous

我正在尝试在单独的线程中运行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”循环的多线程?

3 个答案:

答案 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。进度条没有时间可见:)

谢谢丹尼尔的提示!