je ne peux pas à comprendre pourquoi je reçois un InvalidCastException exécutant le code suivant:CastException essayer d'appeler Action <KeyValuePair <>> délégué de façon asynchrone
var item = new KeyValuePair<string, string>("key", "value");
Action<KeyValuePair<string, string>> kvrAction =
kvr =>Console.WriteLine(kvr.Value);
var result = kvrAction.BeginInvoke(item, null, null);
kvrAction.EndInvoke(result);
Exception Info:
Test method Utilities.Tests.IEnumerableExtensionTests.ProveDelegateAsyncInvokeFailsForKeyValuePair threw exception: System.Runtime.Remoting.RemotingException: The argument type '[key, value]' cannot be converted into parameter type 'System.Collections.Generic.KeyValuePair`2[System.String,System.String]'.
---> System.InvalidCastException: Object must implement IConvertible..
Toute aide serait appréciée =) Ce code semble fonctionner avec tout ce que je lui lance sauf un KeyValuePair <>.
Mise à jour: Il semble que cette condition existe pour toute structure. Je n'avais pas remarqué KeyValuePair <> était une structure et ne faisait donc que tester les classes. Je ne comprends toujours pas pourquoi c'est le cas.
Mise à jour 2: La réponse de Simon a permis de confirmer que ce comportement est inattendu, mais l'implémentation d'un type personnalisé ne fonctionnera pas pour ce que j'essaie de faire. J'essaie d'implémenter une méthode d'extension sur IEnumerable <> pour exécuter un délégué de manière asynchrone pour chaque élément. J'ai remarqué l'erreur exécutant des tests sur un objet Dictionary générique.
public static IEnumerable<T> ForEachAsync<T>(this IEnumerable<T> input, Action<T> act)
{
foreach (var item in input)
{
act.BeginInvoke(item, new AsyncCallback(EndAsyncCall<T>), null);
}
return input;
}
private static void EndAsyncCall<T>(IAsyncResult result)
{
AsyncResult r = (AsyncResult)result;
if (!r.EndInvokeCalled)
{
var d = (Action<T>)((r).AsyncDelegate);
d.EndInvoke(result);
}
}
Je préfère ne pas limiter la méthode avec une contrainte sur T pour assurer les classes ne sont utilisées que si je refondus la méthode comme suit pour contourner le problème avec BeginInvoke mais je ne l'ai pas travaillé avec le directement TreadPool avant et je voudrais m'assurer que je ne manque rien d'important.
public static IEnumerable<T> ForEachAsync<T>(this IEnumerable<T> input, Action<T> act)
{
foreach (var item in input)
ThreadPool.QueueUserWorkItem(obj => act((T)obj), item);
return input;
}
Merci Simon, je suis content de ne pas avoir négligé quelque chose d'idiot. Je suppose que c'est un bogue dans l'infrastructure provoquant l'échec des vérifications de type, ce qui entraîne la vérification de l'interface IConvertable. Malheureusement, la mise en œuvre d'un type personnalisé n'est pas une option pour ce que j'essaie de faire. Je plus de détails à venir. – Venr