2

UIが応答し、進行状況バーが表示されるように、別のスレッドでforループを実行しようとしています。

問題は、それを行う方法がわからないことです:)。このコードでは、プロセスは別のスレッドで開始されますが、コードの次の部分は同時に実行されます。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」ループでマルチスレッドを使用する方法を教えてください。

4

3 に答える 3

5

使用する必要がありますTask.Wait()

これを試して:

TaskEx.Wait();
if (IsIndexMatched == true)
    stkPanelGoto.Visibility = Visibility.Collapsed;

待機時間を制限したい場合は、Wait()time パラメータまたは TimeSpan を指定できます。次に例を示します。

TaskEx.Wait(10000)


CancellationToken、または CancellationToken と時間制限の両方を組み合わせて使用​​することもできます

MSDN のすべてのオプションについて読む:
http://msdn.microsoft.com/en-us/library/dd235635.aspx

于 2012-07-01T08:56:13.027 に答える
2

TaskEx- .NET 4.0 用の非同期ターゲティング パックを使用していますか? その場合、使用await TaskEx.Run(...)- C# 5.0awaitはタスクが完了するまで待機しますが、待機中は 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 をインデックスでトラバースする必要がある場合は、一度リストに変換してからリストをトラバースする方がはるかに高速です。

于 2012-07-01T09:12:14.327 に答える
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. プログレスバーが表示される時間はありません:)

ダニエルさん、ヒントをありがとう!

于 2012-07-01T12:27:04.070 に答える