将函数名称作为操作传递时出现混乱行为

时间:2014-05-22 15:00:59

标签: c# lambda xamarin.android

我正在后台线程中的活动中运行代码。为什么以下两个语句的行为不同?

A)

RunOnUiThread (() => Toast.MakeText(this, "A toast", ToastLength.Short).Show ());

b)中

RunOnUIThread (Toast.MakeText(this, "A toast", ToastLength.Short).Show);

(b)中的代码抛出以下异常:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

所以它看起来像(b)不在UI线程上运行,但为什么呢?

1 个答案:

答案 0 :(得分:2)

让我们先看看第二个例子,因为它更简单。

所以我们有一个方法RunOnUIThread,它接受​​一个委托作为它的参数。要运行这行代码,我们首先需要将第一个参数的表达式计算为值,因此我们执行Toast.MakeText(this, "A toast", ToastLength.Short).Show。这会在当前线程(可能是非UI线程)中立即调用MakeText方法 ,以便创建任何类型MakeText返回的对象。然后,我们将表示对该创建对象的Show方法的调用的委托传递给RunOnUIThread,该方法接受该委托并在UI线程上运行它。

现在该流程实际上并未完成。正如您所看到的,MakeText正在抛出异常,因为您在非UI线程中运行它,所以事情正在破坏。

第一段代码,当它去评估第一个参数的值时,不需要评估任何而不是说有一个方法(由lambda定义)执行运行时Toast.MakeText(this, "A toast", ToastLength.Short).Show()。它不会评估任何代码以创建此委托;它是传递给ShowOnUiThread的委托的正文的一部分。所以这一切都在UI线程中运行,并且工作正常。