2017-11-10 8 views
0

ありがとうございます。 `GridViewに項目を追加するのにforeachを使いたいです。これは、の非同期メソッドで行われます。 私は他の非同期方法からアイテムを取得し、GridViewの中でそれらを表示したい:uwp C#非同期タスクをキャンセルして再実行

public async Task SetGridItems(CancellationToken ct, /* and some items */) 
{ 

    GridItems.clear(); 
    //get two list of item I want 
    var ListA = await getBmethodAsync().AsTask(ct); 
    var ListB = await getAmethodAsync().AsTask(ct); 

    foreach (itemA A in ListA) 
    {  
     GridItem i = new GridItem(); 

     //set name 
     i.name = A.Name; 

     //get icon 
     i.image = img; 

     GridItems.Add(i); 
    } 

    foreach (ItemB b in ListB) 
    { 
     GridItem i = new GridItem(); 
     i.name = b.Name; 
     i.image.SetSource(icon); 

     GridItems.Add(i); 
    } 
} 

コンテンツは便宜上簡略化されています。

私はボタンのクリックハンドラでこのメソッドを実行します。ここでは

private async void check_btn2_Click(object sender, RoutedEventArgs e) 
{  
    if (cts != null) { 
     cts.Cancel(); 
     debug.Text = "cancel a job 4"; 
    } 

    cts = new CancellationTokenSource(); 
    try 
    { 
     await SetGridItems(ct.Token, /* and some items */).AsAsyncAction().AsTask(cts.Token); 
    } 
    catch (OperationCanceledException) { debug.Text = "cancel a job"; } 
} 

は問題です:

私は二回(高速クリック)このボタンをクリックした場合: - 最初のクリックで、イベントコールバックが呼び出され、タスクの実行が開始されます - 何かがGridViewに表示されますが、完了しません(80%で終了) - 2回目のクリックで、GridViewが期待どおりにクリアされ、新しいコンテンツが読み込まれますGriViewはオンです最初のクリックタスクの最後の20%を表示する

なぜ、2回目のクリックではなく、が最初のタスクをキャンセルするのですか?

ネットで長時間探していますが、ナッツは何も見つかりませんでした。助けて、これを達成する方法をいくつか考えてみてください。

私は、私がここに二つの問題を参照英語が得意ではないですし、感謝

+0

に役立ちます。最初の見方では、あなたのコードは正しいようです。私の唯一の関心事は 'SetGridItems(ct.Token、/ * and some items * /)'の後でやっている 'AsAsyncAction().AsTask(cts.Token);'です。既にキャンセルトークンをメソッドに提供している場合は、 'AsTask()'を使って再度取り消す必要はありません。あなたの 'getBmethodAsync()'と 'getAmethodAsync()'にも同じことが当てはまります。あなたはキャンセルトークンを直接提供して、必要な処理を行うことができます。私の推測では、外部の取り消しがこの副作用を生み出しているということです。 – Vincent

+0

VincentとCKIIの助けを借りてくれてありがとう、ct.ThrowIfCancellationRequested(); –

答えて

1

:ヴィンセントはあなたがAsAsyncAction().AsTask(cts.Token);中で少し冗長な方法でキャンセルトークンを渡している、コメントで言ったように

ファーストをボタンのクリックハンドラとメソッド自体の.AsTask(ct);が含まれています。

さらに重要なのは、取り消しトークンをタスクに渡しているにもかかわらず、そのメソッドで決して使用していないことです。キャンセルトークンをタスクに渡すことは、主に並行して使用され、非同期作業には使用されません。一度に実行される複数のタスクの実行状態を調整して照会する方法です。とにかく、それは常に実行コード内のトークン自体の使用に依存します。このように考えると、あなたは操作を取り消していることをタスクオブジェクト自体に伝えていますが、あなたのコードはそれをどのように処理するのか分かりません。

非同期開発では、タスクオブジェクトにキャンセルを渡す必要はありません。多くのタスクの状態を調整する必要がないため、キャンセルのみを実行しているためです。メソッドにトークンを渡し、コードでそれを処理させる必要があります。
だからあなたSetGridItemsメソッドの内部で、このような何かをやってみてください:

public async Task SetGridItems(CancellationToken ct, /* and some items */) 
{ 

    GridItems.clear(); 
    //get two list of item I want 
    var ListA = await getBmethodAsync().AsTask(ct); 
    var ListB = await getAmethodAsync().AsTask(ct); 

    foreach (itemA A in ListA) 
    { 
     ct.ThrowIfCancellationRequested(); 

     GridItem i = new GridItem(); 

     //set name 
     i.name = A.Name; 

     //get icon 
     i.image = img; 

     GridItems.Add(i); 
    } 

    foreach (ItemB b in ListB) 
    { 
     ct.ThrowIfCancellationRequested(); 

     GridItem i = new GridItem(); 
     i.name = b.Name; 
     i.image.SetSource(icon); 

     GridItems.Add(i); 
    } 
} 

GetXMethodAsync方法で同じことを行うようにしてください。このようにして、コードは取り消しを処理する方法を知っています。現在のところ、タスクオブジェクトはキャンセルされる可能性がありますが、停止する場所がわからないため、コードを実行し続けます。
1. https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/task-cancellation
2:あなたは、以下のリンクを参照してくださいすることができ、タスクのキャンセルの詳細について

https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-cancel-a-task-and-its-children

希望これは、あなたが共有しているものだけで何が起こっているかを推測するのは難しいです

+0

ありがとう、それは仕事です! :)、ありがとう、コードはそれを処理する方法を知らない、それは問題です。 –

関連する問題