2017-11-10 4 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 %에서 종료) - 두 번째 클릭시 예상대로 GridView이 지워지고 새로운 내용이로드됩니다. 하지만 GriView은 사용 중입니다. 첫 번째 클릭 작업의 마지막 20 %를 표시합니다.

두 번째 클릭 이 아닌 이유는이 첫 번째 작업을 취소하는 이유는 무엇입니까?

나는 그물에 오랫동안 찾았습니다. 너트는 아무것도 발견하지 못했습니다. 도움을주고이를 달성하는 방법을 알려주십시오. 빈센트으로

먼저 주석 말했다

, 당신은 AsAsyncAction().AsTask(cts.Token);에서와 약간 중복 방법으로 취소 토큰을 전달되고 있습니다

나는 여기에 두 가지 문제를 참조

+0

당신이 공유 한 것만으로 무슨 일이 일어나고 있는지 짐작하기 어렵다 도움이됩니다. 처음에는 코드가 옳았습니다. 나의 유일한 관심사는 SetGridItems (ct.Token,/* 및 some items * /)'후에 수행중인 .AsAsyncAction(). AsTask (cts.Token);입니다. 메소드에 취소 토큰을 이미 제공하고 있다면'AsTask() '를 통해 다시 제공 토큰을 제공 할 필요가 없습니다. 'getBmethodAsync()'와'getAmethodAsync()'도 똑같이 적용된다. 취소 토큰을 직접 제공하고 필요한 것을 소비 할 수있다. 내 생각 엔 외부 취소로 인해 이러한 부작용이 발생하는 것 같습니다. – Vincent

+0

Vincent와 CKII의 도움에 감사드립니다. ct.ThrowIfCancellationRequested(); –

답변

1

영어 잘하지 오전 감사 버튼 클릭 핸들러 및 메서드 자체에 .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

대단히 고마워요, 일합니다 !!! :), 감사합니다, 코드는 그것을 처리하는 방법을 모르는, 그게 문제입니다. –