我似乎无法弄清楚为什么我会收到运行以下代码的 InvalidCastException:
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);
异常信息:
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..
任何帮助将不胜感激 =) 这段代码似乎适用于我扔给它的任何东西,除了 KeyValuePair<>。
更新:似乎任何结构都存在这种情况。我没有注意到 KeyValuePair<> 是一个结构,因此仅使用类进行测试。我仍然不明白为什么会这样。
更新 2:西蒙的回答帮助确认了这种行为是意外的,但是实现自定义类型不适用于我想要做的事情。我正在尝试在 IEnumerable<> 上实现一个扩展方法,以便为每个项目异步执行委托。我注意到针对通用 Dictionary 对象运行测试时出错。
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);
}
}
我宁愿不使用对 T 的约束来限制该方法以确保仅使用类,因此我已按如下方式重构该方法以解决 BeginInvoke 的问题,但我之前没有直接使用 TreadPool 并希望确保我我没有错过任何重要的东西。
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;
}