2016-03-23 12 views
9

Questa è la mia situazione:uso corretto del CancellationToken

private CancellationTokenSource cancellationTokenSource; 
    private CancellationToken cancellationToken; 

    public IoTHub() 
    { 
     cancellationTokenSource = new CancellationTokenSource(); 
     cancellationToken = cancellationTokenSource.Token; 

     receive(); 
    } 

    private void receive() 
    { 
     eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, iotHubD2cEndpoint); 
     var d2cPartitions = eventHubClient.GetRuntimeInformation().PartitionIds; 

     foreach (string partition in d2cPartitions) 
     { 
      ReceiveMessagesFromDeviceAsync(partition, cancellationToken); 
     } 
    } 

    private async Task ReceiveMessagesFromDeviceAsync(CancellationToken ct) 
    { 
     var eventHubReceiver = eventHubClient.GetDefaultConsumerGroup().CreateReceiver(partition, DateTime.UtcNow); 

     while (true) 
     { 
      if(ct.IsCancellationRequested) 
      { 
       break; 
      } 

      EventData eventData = await eventHubReceiver.ReceiveAsync(); 
      if (eventData == null) continue; 

      string data = Encoding.UTF8.GetString(eventData.GetBytes()); 

      // Javascript function with Websocket 
      Clients.All.setMessage(data); 
     } 
    } 

    public void cancelToken() 
    { 
     cancellationTokenSource.Cancel(); 
    } 

Il compito non sarà annullata, quando si chiama il metodo cancelToken. Come mai?

Ho letto il Microsoft guide, un altro StackOverflow domande sulla cancellazione delle attività.

Ma hanno ancora difficoltà a utilizzarli correttamente.

+0

Nel vostro ciclo, sta chiamando un altro metodo asincrono o eseguendo la tua operazione di lunga durata? –

+0

Fornisci un esempio di codice più completo di ciò che stai facendo, ad esempio ciò che viene chiamato ReceiveMessagesFromDeviceAsync? Quale istanza di CancellationToken viene passata in questo metodo? – auburg

+0

Ho effettuato la modifica. – BlueCastle

risposta

6

Si può considerare CancellationToken come una bandiera, che indica se viene ricevuto un segnale di annullamento. Così:

while (true) 
{ 
    //you check the "flag" here, to see if the operation is cancelled, correct usage 
    if(ct.IsCancellationRequested) 
    { 
     break; 
    } 

    //your instance of CancellationToken (ct) can't stop this task from running 
    await LongRunningTask(); 
} 

Se si desidera LongRunningTask da annullare, è necessario utilizzare CancellationToken all'interno del corpo compito e verificare quando necessario, in questo modo:

async Task LongRunningTask() 
{ 
    await DoPrepareWorkAsync(); 

    if (ct.IsCancellationRequested) 
    { 
     //it's cancelled! 
     return; 
    } 

    //let's do it 
    await DoItAsync(); 

    if (ct.IsCancellationRequested) 
    { 
     //oh, it's cancelled after we already did something! 
     //fortunately we have rollback function 
     await RollbackAsync(); 
    } 
} 
+0

Puoi spiegare questo con un esempio? – BlueCastle

+0

@BlueCastle Vedi la modifica. –

+0

Se cancellationTokenSource.Cancel() viene chiamato all'interno del costruttore, l'attività viene annullata. Ma l'attività non verrà annullata quando viene annullato il metodoTokenSource.Cancel() dal metodo cancelToken. – BlueCastle