c# - 将函数名称作为操作传递时的混淆行为

标签 c# lambda xamarin.android

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

一)

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/

相关文章:

C# - 获取调用方法的程序集?

c# - 在 Cake 脚本中找不到 Linq 扩展方法

c# - 继承自 System.Timers.ElapsedEventArgs 使单元测试更容易

c# - 使用日期时间筛选器构建 LINQ to Entities 表达式树

c# - 使用套接字与 MonoDroid 传输数据

xamarin - 获取当前应用程序的构建版本 - Xamarin.Android

c# - 获取 Windows 7 的网络状态

c++ - 递归 lambda : pass by reference or universal reference?

f# - F#: “fun”关键字是否必要?

android - 将 Microsoft 调试器与 Xamarin Android 结合使用