kzen.dev
  • Întrebări
  • Tag-uri
  • Utilizatori
Notificări
Recompense
Înregistrare
După înregistrare, veți primi notificări despre răspunsurile și comentariile la întrebările DVS.
Logare
Dacă aveţi deja un cont, autentificaţi-vă pentru a verifica notificările noi.
Aici vor fi recompensele pentru întrebările, răspunsurile și comentariile adăugate sau modificate.
Mai mult
Sursă
Editează
 Carlo
Carlo
Question

Cum de a anula o Sarcină într-așteaptă?

Am'm a juca cu aceste Windows 8 WinRT sarcini, și am'm încercarea de a anula o sarcina folosind metoda de mai jos, și funcționează la un moment dat. La CancelNotification metoda NU se numește, care te face să crezi că sarcina a fost anulat, dar în fundal sarcina continuă să funcționeze, apoi, după ce-l's-a finalizat, starea de Sarcina este finalizată și nu anulate. Există o modalitate de a opri complet sarcina, atunci când l's-a anulat?

private async void TryTask()
{
    CancellationTokenSource source = new CancellationTokenSource();
    source.Token.Register(CancelNotification);
    source.CancelAfter(TimeSpan.FromSeconds(1));
    var task = Task<int>.Factory.StartNew(() => slowFunc(1, 2), source.Token);

    await task;            

    if (task.IsCompleted)
    {
        MessageDialog md = new MessageDialog(task.Result.ToString());
        await md.ShowAsync();
    }
    else
    {
        MessageDialog md = new MessageDialog("Uncompleted");
        await md.ShowAsync();
    }
}

private int slowFunc(int a, int b)
{
    string someString = string.Empty;
    for (int i = 0; i < 200000; i++)
    {
        someString += "a";
    }

    return a + b;
}

private void CancelNotification()
{
}
147 2012-04-13T01:53:19+00:00 4
 Carlo
Carlo
Întrebarea editată 13 aprilie 2012 в 2:41
Programare
c#
task-parallel-library
.net-4.5
Solution / Answer
Stephen Cleary
Stephen Cleary
13 aprilie 2012 в 2:43
2012-04-13T02:43:33+00:00
Mai mult
Sursă
Editează
#15927416

Citiți pe Anulare (care a fost introdus în .NET 4.0 și este în mare parte neschimbat de atunci) și Task-Based Model Asincron, care oferă orientări privind modul de utilizare `CancellationToken cu "asincron" metode.

Pentru a rezuma, voi trece la un `CancellationToken în fiecare metoda care acceptă anularea, și că metoda trebuie să verifice periodic.

private async Task TryTask()
{
  CancellationTokenSource source = new CancellationTokenSource();
  source.CancelAfter(TimeSpan.FromSeconds(1));
  Task<int> task = Task.Run(() => slowFunc(1, 2, source.Token), source.Token);

  // (A canceled task will raise an exception when awaited).
  await task;
}

private int slowFunc(int a, int b, CancellationToken cancellationToken)
{
  string someString = string.Empty;
  for (int i = 0; i < 200000; i++)
  {
    someString += "a";
    if (i % 1000 == 0)
      cancellationToken.ThrowIfCancellationRequested();
  }

  return a + b;
}
216
0
 sonatique
sonatique
9 octombrie 2015 в 1:49
2015-10-09T13:49:23+00:00
Mai mult
Sursă
Editează
#15927491

Sau, pentru a evita modificarea slowFunc (daca nu - 't au acces la codul sursă, de exemplu):

var source = new CancellationTokenSource(); //original code
source.Token.Register(CancelNotification); //original code
source.CancelAfter(TimeSpan.FromSeconds(1)); //original code
var completionSource = new TaskCompletionSource<object>(); //New code
source.Token.Register(() => completionSource.TrySetCanceled()); //New code
var task = Task<int>.Factory.StartNew(() => slowFunc(1, 2), source.Token); //original code

//original code: await task;  
await Task.WhenAny(task, completionSource.Task); //New code

Puteți folosi, de asemenea, frumos extensia metode de https://github.com/StephenCleary/AsyncEx și se pare la fel de simplu ca:

await Task.WhenAny(task, source.Token.AsTask());
 sonatique
sonatique
Răspuns editat 14 martie 2018 в 6:16
35
0
 kjbartel
kjbartel
20 noiembrie 2018 в 1:01
2018-11-20T13:01:29+00:00
Mai mult
Sursă
Editează
#15927511

Un caz care a't a fost acoperit este cum să se ocupe de anulare în interiorul de o metoda asincron. Luați, de exemplu, un caz simplu în care aveți nevoie pentru a încărca unele date de la un serviciu pentru a calcula ceva și apoi să se întoarcă rezultatele.

public async Task<Results> ProcessDataAsync(MyData data)
{
    var client = await GetClientAsync();
    await client.UploadDataAsync(data);
    await client.CalculateAsync();
    return await client.GetResultsAsync();
}

Dacă doriți să sprijine anulare atunci cel mai simplu mod ar fi să treacă într-un token-ul și verificați dacă acesta a fost anulat între fiecare metoda asincron apel (sau folosind ContinueWith). Dacă acestea sunt foarte lungă de funcționare apeluri deși ai putea fi un timp de așteptare pentru a anula. Am creat un mic ajutor metodă de a eșua în loc cât mai curând anulat.

public static class TaskExtensions
{
    public static async Task<T> WaitOrCancel<T>(this Task<T> task, CancellationToken token)
    {
        token.ThrowIfCancellationRequested();
        await Task.WhenAny(task, token.WhenCanceled());
        token.ThrowIfCancellationRequested();

        return await task;
    }

    public static Task WhenCanceled(this CancellationToken cancellationToken)
    {
        var tcs = new TaskCompletionSource<bool>();
        cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).SetResult(true), tcs);
        return tcs.Task;
    }
}

Deci, să-l folosească atunci doar adauga `.WaitOrCancel(token) la orice apel asincron:

public async Task<Results> ProcessDataAsync(MyData data, CancellationToken token)
{
    Client client;
    try
    {
        client = await GetClientAsync().WaitOrCancel(token);
        await client.UploadDataAsync(data).WaitOrCancel(token);
        await client.CalculateAsync().WaitOrCancel(token);
        return await client.GetResultsAsync().WaitOrCancel(token);
    }
    catch (OperationCanceledException)
    {
        if (client != null)
            await client.CancelAsync();
        throw;
    }
}

Rețineți că acest lucru nu va opri Sarcina ai fost de așteptare pentru și va continua să ruleze. Te'll nevoie pentru a utiliza un alt mecanism pentru a opri, cum ar fi CancelAsync apel în exemplu, sau mai bine încă trece în aceeași `CancellationToken la "Sarcină", astfel încât se poate ocupa anularea în cele din urmă. Încercarea de a abandona filet e't recomandat.

 kjbartel
kjbartel
Răspuns editat 6 august 2019 в 7:08
11
0
 Smeegs
Smeegs
2 august 2012 в 1:22
2012-08-02T01:22:15+00:00
Mai mult
Sursă
Editează
#15927486

Vreau doar pentru a adăuga la deja răspunsul acceptat. Am fost blocat pe aceasta, dar am fost de gând pe un drum diferit la manipularea eveniment complet. Mai degrabă decât de funcționare așteaptă, am adăuga un finalizată handler pentru sarcina.

Comments.AsAsyncAction().Completed += new AsyncActionCompletedHandler(CommentLoadComplete);

În cazul în care de tratare a evenimentelor arată astfel

private void CommentLoadComplete(IAsyncAction sender, AsyncStatus status )
{
    if (status == AsyncStatus.Canceled)
    {
        return;
    }
    CommentsItemsControl.ItemsSource = Comments.Result;
    CommentScrollViewer.ScrollToVerticalOffset(0);
    CommentScrollViewer.Visibility = Visibility.Visible;
    CommentProgressRing.Visibility = Visibility.Collapsed;
}

Cu acest traseu, tot manipulare este deja făcut pentru tine, atunci când sarcina este anulat doar declanșează event handler și puteți vedea dacă acesta a fost anulat acolo.

 EluciusFTW
EluciusFTW
Răspuns editat 19 decembrie 2017 в 4:16
6
0
Adăugati o întrebare
Categorii
Toate
Tehnologii
Cultură
Viață / Artă
Stiință
Profesii
Afaceri
Utilizatori
Toate
Nou
Populare
1
工藤 芳則
Înregistrat 6 zile în urmă
2
Ирина Беляева
Înregistrat 1 săptămână în urmă
3
Darya Arsenyeva
Înregistrat 1 săptămână în urmă
4
anyta nuam-nuam (LapuSiK)
Înregistrat 1 săptămână în urmă
5
Shuhratjon Imomkulov
Înregistrat 1 săptămână în urmă
ES
ID
JA
KO
RO
RU
© kzen.dev 2023
Sursă
stackoverflow.com
în cadrul licenței cc by-sa 3.0 cu atribuire