Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception (sometimes) is thrown when awaiting a method with dynamic argument

I have the following code:

string commandText = await _client
       .GetCommandTextAsync("Products", x.ProductName == "Chai");

The second parameter (x.ProductName == "Chai") contains a dynamic clause (x.ProductName), so the resulting expression is also dynamic. When this code is executed on .NET 4.0, sometimes it throws the following exception:

System.InvalidCastException Unable to cast object of type 'System.Runtime.CompilerServices.TaskAwaiter`1[System.String]' to type 'System.Runtime.CompilerServices.INotifyCompletion'.

The exception is not thrown if I explicitly case the method result to Task:

string commandText = await (Task<string>)_client
       .GetCommandTextAsync("Products", x.ProductName == "Chai");

Is there a more elegant way to resolve this problem (without casting every single line of code that awaits for a dynamic result), or is this a known problem with using TPL on .NET 4.0.

I haven't experienced this on .NET 4.5.

like image 540
Vagif Abilov Avatar asked Oct 21 '22 10:10

Vagif Abilov


1 Answers

Here is a theory:

According to the TaskAwaiter definition:

[HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
public struct TaskAwaiter : ICriticalNotifyCompletion, INotifyCompletion

it seems that TaskAwaiter is an INotifyCompletion. You said you have dynamic clause in your code. As MS states dynamic objects are mostly behaves like object. Thus casting is required in the code which is handled by run-time or compiler.

You also stated that platform is Xamarin iOS. Which possibly utilizing HostProtectionAttribute for example to block usage of some classes or etc.

The TaskAwaiter implementation is marked with SecurityAction.LinkDemand and again if we check MSDN it says:

...
LinkDemand (do not use in the .NET Framework 4)
...

So conclusion is: The platform which code is running, is lacking security implementations required by Host Protection and methods are not invoked (while security is not working properly) Casting is one of "secure" operation thus this type of runtime casting fails.

if you explicitly cast like you did, there is no problem because compiler does not add the "buggy" code.

like image 51
Mert Gülsoy Avatar answered Oct 23 '22 07:10

Mert Gülsoy