source net iscancellationrequested how cancellationtoken c# asynchronous task-parallel-library cancellation-token

net - how to use cancellationtoken c#



ParĂ¡metro predeterminado para CancellationToken (5)

¿Hay alguna forma de tener un valor predeterminado para CancellationToken?

Desafortunadamente, esto no es posible, ya que CancellationToken.None no es una constante de tiempo de compilación, que es un requisito para los valores predeterminados en los argumentos opcionales.

Sin embargo, puede proporcionar el mismo efecto al hacer un método sobrecargado en lugar de tratar de usar los parámetros predeterminados:

Task<x> DoStuff(...., CancellationToken ct) { //... } Task<x> DoStuff(....) { return DoStuff(...., CancellationToken.None); }

Tengo un código asíncrono al que me gustaría agregar un CancelToken. Sin embargo, hay muchas implementaciones donde esto no es necesario, por lo que me gustaría tener un parámetro predeterminado, quizás CancellationToken.None. Sin embargo,

Task<x> DoStuff(...., CancellationToken ct = null)

rendimientos

No se puede usar un valor de tipo '''' como parámetro predeterminado porque no hay conversiones estándar para escribir ''System.Threading.CancellationToken''

y

Task<x> DoStuff(...., CancellationToken ct = CancellationToken.None)

El valor de parámetro predeterminado para ''ct'' debe ser una constante en tiempo de compilación

¿Hay alguna forma de tener un valor predeterminado para CancellationToken?


Aquí hay varias soluciones, en orden descendente de bondad general:

1. Usar el default(CancellationToken) como valor predeterminado:

Task DoAsync(CancellationToken ct = default(CancellationToken)) { … }

Semánticamente, CancellationToken.None sería el candidato ideal para el valor predeterminado, pero no se puede usar como tal porque no es una constante en tiempo de compilación. default(CancellationToken) es la segunda mejor opción porque es una constante en tiempo de compilación y está oficialmente documentado para ser equivalente a CancellationToken.None .

2. Proporcionar una sobrecarga de método sin un parámetro CancellationToken :

O bien, si prefiere las sobrecargas de métodos sobre los parámetros opcionales (consulte this y this pregunta sobre ese tema):

Task DoAsync(CancellationToken ct) { … } // actual method always requires a token Task DoAsync() => DoAsync(CancellationToken.None); // overload producing a default token

Para los métodos de interfaz, lo mismo se puede lograr utilizando métodos de extensión:

interface IFoo { Task DoAsync(CancellationToken ct); } static class Foo { public static Task DoAsync(this IFoo foo) => foo.DoAsync(CancellationToken.None); }

Esto da como resultado una interfaz más delgada y ahorra a los implementadores escribir explícitamente la sobrecarga del método de reenvío.

3. Haciendo el parámetro nulable y usando null como valor por defecto:

Task DoAsync(…, CancellationToken? ct = null) { … ct ?? CancellationToken.None … }

Me gusta menos esta solución porque los tipos anulables vienen con una sobrecarga de tiempo de ejecución pequeña, y las referencias al token de cancelación se vuelven más detalladas debido al operador nulo coalescente. .


Otra opción es usar un Nullable<CancellationToken> , establecerlo por defecto en null , y tratarlo dentro del método:

Task<x> DoStuff(...., CancellationToken? ct = null) { var token = ct ?? CancellationToken.None; ... }


Resulta que los siguientes trabajos:

Task<x> DoStuff(...., CancellationToken ct = default(CancellationToken))

que, de acuerdo con la documentación , se interpreta de la misma manera que CancellationToken.None :

También puede usar la declaración default(CancellationToken) C # default(CancellationToken) para crear un token de cancelación vacío.


La respuesta de Tofutim es de una manera, pero de los comentarios veo que la gente tiene problemas con eso.

En ese caso, sugerí que uno puede tener un método de la siguiente manera:

Task<x> DoStuff(...., CancellationToken ct) { }

y sobrecargarlo como:

Task<x> DoStuff(....) { return DoStuff(...., CancellationToken.None); }

Esto compila, porque el valor de CancellationToken.None no es necesario en tiempo de compilación.