如何从事件处理程序中取消订阅事件?
How to unsubscribe an event from inside the event handler?
我的代码订阅了一个事件,它需要在处理完事件后取消订阅 (Dispose
)。然而,这看起来像是先有鸡还是先有蛋的问题。使用 rec
不起作用,我找不到如何操作。
有什么好的模式可以绕过这个限制吗?
let process = new Process()
let exitSubscription = process.Exited.Subscribe (
fun evntArg ->
exitSubscription.Dispose() <---------- Compiler complains here
// do more something here.
)
(你在问题中说 rec
不起作用,但没有说明原因或方式;所以我将忽略此答案的那部分)
实现此目的的一种方法 是使用 rec
关键字声明值“递归”。这将允许值初始化代码引用值本身 - 就像递归函数一样。
let rec exitSubscription : IDisposable = process.Exited.Subscribe (
fun evntArg ->
exitSubscription.Dispose()
// do more something here.
)
这会起作用,但也会产生一个警告说“这是一个递归值,我无法判断你是否在构造它时实际访问它,所以你必须确保你不这样做,如果你这样做,这将是一个运行时错误”。
请注意,您还必须向变量添加类型签名,否则编译器无法理解它并抱怨它可能没有 Dispose
方法。
另一种方法是使变量可变,然后对其进行变异:
let mutable exitSubscription : IDisposable = null
exitSubscription <- process.Exited.Subscribe (
fun evntArg ->
exitSubscription.Dispose()
// do more something here.
)
这里你也必须使用类型签名(出于同样的原因),你必须用null
初始化它,因为没有未初始化的变量。
此外,这有点不安全,因为变量是可变的,而这始终是错误的来源。只要你 pinky-promise 不改变它(超出这个初始化),你就没问题。
但是“正确”的方法是使用可观察组合器将可观察对象限制为仅一个元素。这样您就不必明确取消订阅,这样总是更可靠:
#r "nuget: System.Reactive"
open System.Reactive.Linq
process.Exited.Take(1).Subscribe (
fun evntArg ->
// do more something here.
)
我的代码订阅了一个事件,它需要在处理完事件后取消订阅 (Dispose
)。然而,这看起来像是先有鸡还是先有蛋的问题。使用 rec
不起作用,我找不到如何操作。
有什么好的模式可以绕过这个限制吗?
let process = new Process()
let exitSubscription = process.Exited.Subscribe (
fun evntArg ->
exitSubscription.Dispose() <---------- Compiler complains here
// do more something here.
)
(你在问题中说 rec
不起作用,但没有说明原因或方式;所以我将忽略此答案的那部分)
实现此目的的一种方法 是使用 rec
关键字声明值“递归”。这将允许值初始化代码引用值本身 - 就像递归函数一样。
let rec exitSubscription : IDisposable = process.Exited.Subscribe (
fun evntArg ->
exitSubscription.Dispose()
// do more something here.
)
这会起作用,但也会产生一个警告说“这是一个递归值,我无法判断你是否在构造它时实际访问它,所以你必须确保你不这样做,如果你这样做,这将是一个运行时错误”。
请注意,您还必须向变量添加类型签名,否则编译器无法理解它并抱怨它可能没有 Dispose
方法。
另一种方法是使变量可变,然后对其进行变异:
let mutable exitSubscription : IDisposable = null
exitSubscription <- process.Exited.Subscribe (
fun evntArg ->
exitSubscription.Dispose()
// do more something here.
)
这里你也必须使用类型签名(出于同样的原因),你必须用null
初始化它,因为没有未初始化的变量。
此外,这有点不安全,因为变量是可变的,而这始终是错误的来源。只要你 pinky-promise 不改变它(超出这个初始化),你就没问题。
但是“正确”的方法是使用可观察组合器将可观察对象限制为仅一个元素。这样您就不必明确取消订阅,这样总是更可靠:
#r "nuget: System.Reactive"
open System.Reactive.Linq
process.Exited.Take(1).Subscribe (
fun evntArg ->
// do more something here.
)