我正在尝试在项目启动时运行简单计时器:
type NJHomeViewModel(config : Config) as X =
inherit ViewModelBase()
do
(X.Timer : Timer).Elapsed.Add(fun args -> X.OnTimedEvent(args))
(X.Timer : Timer).Interval <- 3000.0
(X.Timer : Timer).Enabled <- true
(X.Timer : Timer).Start()
member X.Timer = new Timer()
member X.OnTimedEvent args = X.Change()
所以我希望每3秒运行一次X.Change()函数,它不会以这种方式工作,即使我将它添加到按钮也没有改变。
member X.Next =
new RelayCommand((fun canExecute -> true),
(fun action ->
(X.Timer : Timer).Elapsed.Add(fun args -> X.OnTimedEvent(args))
(X.Timer : Timer).Interval <- 3000.0
(X.Timer : Timer).Enabled <- true
(X.Timer : Timer).Start() ))
使用“勾号”操作启动计时器的正确方法是什么?
答案 0 :(得分:3)
考虑使用异步循环优先于使用计时器;见例如。
http://lorgonblog.wordpress.com/2010/03/27/f-async-on-the-client-side/
有一个像
这样的例子async {
while true do
do! Async.Sleep 1000
textBox.Text <- System.DateTime.Now.ToString()
} |> Async.StartImmediate
答案 1 :(得分:2)
member X.Timer = new Timer()
这会创建一个带有getter的属性,并在每次创建新Timer时访问此属性。
为避免这种情况,您可以使用let绑定:
type NJHomeViewModel(config : Config) as X =
inherit ViewModelBase()
let timer = new Timer()
do
timer.Elapsed.Add(fun args -> X.OnTimedEvent(args))
timer.Interval <- 3000.0
timer.Enabled <- true
timer.Start()
member X.Timer = timer
member X.OnTimedEvent args = X.Change()
答案 2 :(得分:1)
您正在使用基于服务器的System.Timers.Timer公开Elapsed事件。还有其他可用的计时器(例如,您可以提供回调方法的System.Threading.Timer或可以订阅Tick事件的Windows.Forms.Timer,因此您需要选择最适合您的应用程序的计时器和你的用例。 MSDN有一篇关于何时使用哪个.NET Timer here
的文章对于您正在使用的计时器,Elapsed事件仅在某种状态下才会运行一次。这可能是你的问题。来自MSDN
如果Enabled设置为true且AutoReset设置为false,则为Timer 仅提升一次Elapsed事件,第一次是间隔 为止。
线程计时器看起来像
new Timer((fun _ -> YourMethod), null, 1000, 1000)
Windows.Forms.Timer看起来像
formsTimer.Tick.Add( fun _ -> YourMethod())
在WPF中,您还可以使用DispatcherTimer(更多here)。在F#中,这看起来像
let tmr = new DispatcherTimer(Interval = TimeSpan.FromSeconds(1.0))
tmr.Tick.Add( fun _ -> YourMethod())
tmr.Start()
在another question on SO中对Forms.Timer和DispatcherTimer进行了简要比较,可以帮助您为应用选择合适的。