Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net System.Timers.Timer和数据绑定_Vb.net - Fatal编程技术网

Vb.net System.Timers.Timer和数据绑定

Vb.net System.Timers.Timer和数据绑定,vb.net,Vb.net,如果我有一个实现INotifyPropertyChanged的类,并且该类中有一个绑定到表单标签的属性,那么如果我从System.Timers.Timer.Appeased事件处理程序设置属性值,如何避免出现跨线程异常 下面的代码演示了该异常 Imports System.ComponentModel Imports System.Timers Public Class Form1 Private thisClass As New aClass Private Wit

如果我有一个实现INotifyPropertyChanged的类,并且该类中有一个绑定到表单标签的属性,那么如果我从System.Timers.Timer.Appeased事件处理程序设置属性值,如何避免出现跨线程异常

下面的代码演示了该异常

    Imports System.ComponentModel
Imports System.Timers

Public Class Form1

    Private thisClass As New aClass
    Private WithEvents tmr As New System.Timers.Timer()
    Private lbl As System.Windows.Forms.Label
    Public Sub New()

        InitializeComponent()

        'create the label and add it to the form
        lbl = New Label
        lbl.Text = "some text"
        Me.Controls.Add(lbl)

        'set the data binding and start a timer
        lbl.DataBindings.Add("Text", thisClass, "X")
        tmr.Interval = 1000
        AddHandler tmr.Elapsed, AddressOf tmr_Elapsed
        tmr.Start()

    End Sub

    Private Sub tmr_Elapsed(sender As Object, e As ElapsedEventArgs)
        'change the property value when the timer elapses
        thisClass.X = Guid.NewGuid.ToString

    End Sub
End Class

Public Class aClass
    Implements INotifyPropertyChanged

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Private _x As String = ""
    Public Property X As String
        Get
            Return _x
        End Get
        Set(value As String)
            _x = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("X"))
        End Set
    End Property
End Class

另一种方法是使用异步方法在同一线程上不断更新代码

Public Class MyForm
  Private _viewmodel As MyViewModel 
  Private _intervalTask As Task
  Private _canContinueIntervalRunning As Boolean

  Public Sub New()
    InitializeComponent()
    _viewmodel = New MyViewModel()

    CreateLabel() ' Create label and bind to viewmodel property
    
    ' Start interval without blocking this code execution
    ' Later we can use this saved task to make sure that task is complete
    _canContinueIntervalRunning = True
    _intervalTask = StartInterval()
  End Sub

  Private Async Function StartInterval() As Task
    While _canContinueIntervalRunning
      Await Task.Delay(1000)
      _viewmodel.X = Guid.NewGuid().ToString()
    End While
  End Function

  Private Async Sub FormClosing(sender as Object, e as FormClosingEventArgs) Handles MyForm.FormClosing
    ' Set "flag" to false and wait for task to complete
    _canContinueIntervalRunning = False
    Await _intervalTask
  End Sub
End Class
使用
wait Task.Delay(1000)
下一行将在同一个线程上执行,这允许在不需要额外努力的情况下更新表单控件


这是使用布尔标志的简单方法,另一种方法是使用取消令牌,您可以将其传递给
任务。延迟
-然后表单不需要等待额外的秒,但是可以立即取消
延迟

是否有理由使用
系统.Timers.Timer
而不是
系统.Windows.Forms.Timer
?如果您确实有一个,请使用
Me.Invoke(新操作(Sub()thisClass.X=Guid.NewGuid.ToString())
。如果没有,只需切换到
System.Windows.Forms.Timer
,其
Tick
事件在主(UI)线程上运行。@41686d6564的重复项-我是否必须使用系统计时器,否,但在这种情况下,窗体计时器将浪费UI时间片。另外,我不认为这个问题是重复的。在您的重复文章中,很明显需要调用。有了数据绑定,就没有机会调用“不,我没有”,那么,请这样做。将
thisClass.X=Guid.NewGuid.ToString
行替换为我第一条评论中的代码,如果它不起作用,请告诉我(扰流板警报:它会起作用)。我很清楚您使用的是数据绑定,我在上面解释了引发异常的原因,以及使用
Invoke()
将如何防止这种情况。如果你还有任何问题,请告诉我。我很乐意帮忙:)“在这种情况下,表单计时器会浪费UI时间片”。显然,如果您需要在事件处理程序中做的唯一一件事是影响UI,那么就不会发生。任何影响UI的操作都必须在UI线程上执行。任何必须在UI线程上执行的操作都不会浪费UI线程的时间。