我正在后台线程的事件中运行代码。为什么以下两个语句的行为不同?
一)
RunOnUiThread (() => Toast.MakeText(this, "A toast", ToastLength.Short).Show ());
二)
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 线程上运行,但为什么呢?
最佳答案
我们先看第二个例子,因为比较简单。
所以我们有一个方法 RunOnUIThread
,它接受一个委托(delegate)作为它的参数。要运行这行代码,我们首先需要将第一个参数的表达式计算为一个值,因此我们执行 Toast.MakeText(this, "A toast", ToastLength.Short).Show
。这会在当前线程(可能是非 UI 线程)中立即调用MakeText
方法,以创建任何类型的MakeText
对象返回。然后,我们将表示对已创建对象的 Show
方法的调用的委托(delegate)传递给 RunOnUIThread
,它接受该委托(delegate)并在 UI 线程上运行它。
现在这个过程实际上并没有运行完成。如您所见,MakeText
正在抛出异常,因为您在非 UI 线程中运行它,因此出现问题。
第一段代码,当它去评估第一个参数的值时,不需要评估任何,除了说有一个方法(由 lambda 定义)执行Toast.MakeText(this, "A toast", ToastLength.Short).Show()
运行时。它不评估任何代码以创建此委托(delegate);它是传递给 ShowOnUiThread
的委托(delegate)的 body 的一部分。所以它都在 UI 线程中运行,一切正常。
关于c# - 将函数名称作为操作传递时的混淆行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23810489/