While converting one of our products to use the async mechanism I discovered a strange .NET Framework behavior.
Suppose you have a following code in your command button:
decimal xyz = GetData()[0];
Let’s say the GetData implementation happens to be resource intensive which causes your UI to be unresponsive when the button is clicked. To fix this, you will convert the method into an awaitable one, such as:
public async Task<decimal[]> GetDataAsync()
{
return await Task.Run(() =>
{
// This would be something that takes a long time to return
return new decimal[] { 1, 2, 3 };
});
}
Finally, you will change your invocation code in the command button to:
decimal xyz = (await GetDataAsync())[0];
Once you compile and run the code, it will produce System.InvalidProgramException exception stating that Common Language Runtime detected an invalid program.
After some investigation I found out that the issue occurs only if ALL of these conditions are met:
- You are using an array
- The array is type of decimal
- You want to await the result and get an item of the array in a one-liner
That being said, if you modify the example above into using an array of int for example, the exception will not be raised and everything will work as expected.
Similarly, if you split the invocation code in two lines, the error will go away as well:
decimal[] abc = await GetDataAsync();
decimal xyz = abc[0];
Even though I agree that this code is much clearer than the original one-liner, the reason why the original code fails to compile remains a mystery to me. A possible bug in the .NET Framework?
Additionally, further testing revealed that this issue is present in .NET Framework 4.5, 4.5.1 as well as in the Async Targeting Pack for .NET Framework 4.0.
The code won’t fail on compilation time, but only on run time, when the async code is compiled on-demand, so watch out for this one!
No comments:
Post a Comment