Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NullException when using Dispatcher.AwaitableRunAsync with Action #608

Closed
deltakosh opened this issue Nov 11, 2016 · 29 comments
Closed

NullException when using Dispatcher.AwaitableRunAsync with Action #608

deltakosh opened this issue Nov 11, 2016 · 29 comments
Labels
bug 🐛 An unexpected issue that highlights incorrect behavior helpers ✋

Comments

@deltakosh
Copy link
Contributor

No description provided.

@deltakosh deltakosh added bug 🐛 An unexpected issue that highlights incorrect behavior helpers ✋ labels Nov 11, 2016
@deltakosh
Copy link
Contributor Author

taskCompletionSource.SetResult(await function().ConfigureAwait(false)); will raise NulLException if function return null

@deltakosh
Copy link
Contributor Author

deltakosh commented Nov 11, 2016

Ping @Code-ScottLe

@Code-ScottLe
Copy link
Contributor

Code-ScottLe commented Nov 11, 2016

Ooohf. Dang. I'll get on it after work.

@Code-ScottLe
Copy link
Contributor

@deltakosh Do you have an example of this failing?

@IbraheemOsama
Copy link
Member

I'm Publishing a fix in 2 mins but what cause it

int crossThreadReturnedValue = await Task.Run(async () =>
{
int returnedFromUIThread = await DispatcherHelper.ExecuteOnUIThreadAsync(() =>
{
NormalTextBlock.Text = "Updated from a random thread!";
return null;
});

            return returnedFromUIThread + 1;
        });

@Code-ScottLe
Copy link
Contributor

int returnedFromUIThread = await DispatcherHelper.ExecuteOnUIThreadAsync(() => { NormalTextBlock.Text = "Updated from a random thread!"; return null; });

This call doesn't specified the return value type T, this must have been compile-time error isn't it? Or maybe i'm missing something here

@IbraheemOsama
Copy link
Member

No the return type is Task :) not the T

@IbraheemOsama
Copy link
Member

IbraheemOsama commented Nov 11, 2016

I was wondering how this happening until I saw Func of Task of T , Task is the return type :) that's why it allowed null.

@Code-ScottLe
Copy link
Contributor

but in the code above, the call is awaited the returned Task and try to assign the returned value to an int, which should be caught by Intellisense / Compiler right? Or should i ignore that part ? :)

@IbraheemOsama
Copy link
Member

lol :) you're totally right maybe we should report this to the VS team.

@IbraheemOsama
Copy link
Member

Or maybe it is designed to be like that.

@Code-ScottLe
Copy link
Contributor

Ya, i was like, "wait what?, how does one that even pass the compiler!?"

The function argument shouldn't be null at any given call, unless they especially pass null in, and await can deal with null just fine I believe.

@IbraheemOsama
Copy link
Member

No the Task that is returned from the function is the Null not the func it self and that's why when the task(Null).configureAwait will throw a null reference :)

@Code-ScottLe
Copy link
Contributor

Oh! I see. So the entire returned Task itself is null? In which case does that happen?

@IbraheemOsama
Copy link
Member

int returnedFromUIThread = await DispatcherHelper.ExecuteOnUIThreadAsync(() =>
{
NormalTextBlock.Text = "Updated from a random thread!";
return null;
});

@Code-ScottLe
Copy link
Contributor

Hmm, i'm still scratching my head over here on how this call ended up using the Func<Task> Overload.

() => { NormalTextBlock.Text = "Updated from a random thread!";
return null;});

is an Action, which then be Func<object> when it get down to AwaitableRunAsync overload that use Func<T>, which shouldn't have any await and async, Somebody enlighten me please haha :)

@IbraheemOsama
Copy link
Member

IbraheemOsama commented Nov 11, 2016

I was just like that the moment I saw it :) but after investigation I noticed the Task<int> and the return null refere to the task not the int :)

@Code-ScottLe
Copy link
Contributor

So is the returned value of the call above (not the lambda) is Task<int> ?

@IbraheemOsama
Copy link
Member

Yes :)

@Code-ScottLe
Copy link
Contributor

If that is the case, then i don't get it why the lambda passed compiling then, int is not nullable without the verify specific int? declaration and the return null statement must have been caught on compile time. Any ideas?

@Code-ScottLe
Copy link
Contributor

ping @lukasf

@IbraheemOsama
Copy link
Member

let me explain it from my point of view :)
Method ExecuteOnUIThreadAsync<T>(Func<Task<T>> function) tasks a func of task of T (int) right so whatever is return from this function is a Task of T or int, if you returned an int (1) as the main page example, it returns Task as its result is 1 and we can have this result once we await.
but what if you returned a null ? should it refer to the generic object which is int or the Task it self and I see that VS and CLR took the path Task is the null not the generic object it self is the null which we could have an open discussion about which path should be followed :)

@Code-ScottLe
Copy link
Contributor

Yeah, i understand your reasoning. So it is almost like :

"hey, i am expecting a function that return either int or Task<int>. This lambda return null and int is not nullable, so let's pick the overload that has the signature of Task<int> instead" .

But the call is a straight forward DispatcherHelper.ExecuteOnUIThreadAsync without the generic part <T>. So there are only 2 overloads that can be called upon. One uses Action and one uses Func<Task> . And somehow this ended up returning a Task<int> that can be awaited with an int is beyond me.

@deltakosh
Copy link
Contributor Author

Thank you guys! it was an interesting one :)

@IbraheemOsama
Copy link
Member

heheh yes :) for a second I thought VS has a bug :D

@IbraheemOsama
Copy link
Member

No, the code uses the generic one :)
int returnedFromUIThread = await DispatcherHelper.ExecuteOnUIThreadAsync<int>(() => { NormalTextBlock.Text = "Updated from a random thread!"; return 1; });

but I see that github removed the greater than sign :)

@Code-ScottLe
Copy link
Contributor

Ohhh... now that makes sense now... you got me for a solid hour there hahahahaha. Thanks for fixing this, I appreciate it. :)

@IbraheemOsama
Copy link
Member

You're welcome :)

@lukasf
Copy link
Contributor

lukasf commented Nov 11, 2016

Wow, nice one! Pretty weird but somehow it makes sense, from the compiler's point of view... :)

@ghost ghost locked as resolved and limited conversation to collaborators Nov 26, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug 🐛 An unexpected issue that highlights incorrect behavior helpers ✋
Projects
None yet
Development

No branches or pull requests

4 participants