我有以下代码:
string commandText = await _client
.GetCommandTextAsync("Products", x.ProductName == "Chai");
第二个参数(x.ProductName ==“Chai”)包含一个动态子句(x.ProductName),因此生成的表达式也是动态的。在.NET 4.0上执行此代码时,有时会抛出以下异常:
System.InvalidCastException无法转换类型的对象 输入'System.Runtime.CompilerServices.TaskAwaiter`1 [System.String]' 'System.Runtime.CompilerServices.INotifyCompletion'。
如果我将方法结果明确地说明为Task:
,则不会引发异常string commandText = await (Task<string>)_client
.GetCommandTextAsync("Products", x.ProductName == "Chai");
是否有一种更优雅的方法来解决此问题(不会抛出等待动态结果的每一行代码),或者这是在.NET 4.0上使用TPL的已知问题。
我在.NET 4.5上没有遇到过这种情况。
答案 0 :(得分:3)
这是一个理论:
根据TaskAwaiter定义:
[HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
public struct TaskAwaiter : ICriticalNotifyCompletion, INotifyCompletion
似乎 TaskAwaiter 是 INotifyCompletion 。你说你的代码中有动态子句。由于MS状态动态对象的行为大多与对象相似。因此,在运行时或编译器处理的代码中需要进行转换。
您还说该平台是Xamarin iOS。例如,可能利用 HostProtectionAttribute 来阻止某些类的使用等。
TaskAwaiter实现标有 SecurityAction.LinkDemand ,如果我们检查MSDN它会说:
...
LinkDemand (do not use in the .NET Framework 4)
...
所以结论是:代码运行的平台缺少Host Protection所需的安全实现,并且没有调用方法(安全性不能正常工作)Casting是&#34; secure&#34;因此这种类型的运行时转换失败。
如果你像你一样明确地投射,那就没有问题,因为编译器没有添加&#34; buggy&#34;代码。