Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.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
.net System.Windows.Forms.Timer和实例变量_.net_Event Handling_Thread Safety_Instance Variables - Fatal编程技术网

.net System.Windows.Forms.Timer和实例变量

.net System.Windows.Forms.Timer和实例变量,.net,event-handling,thread-safety,instance-variables,.net,Event Handling,Thread Safety,Instance Variables,我有一个按钮点击事件处理程序,它更新包含表单中的私有、非共享实例变量 我还有一个System.Windows.Forms.Timer,它的勾选事件在按钮点击事件完成几秒钟后发生 我的问题是:勾选事件处理程序为什么有时(经常)看到该实例变量的前一个值?(我认为System.Windows.Forms.Timer对于实例变量是线程安全的。) 相关问题:这种情况在速度非常快的四处理器计算机上经常发生,但在速度较慢的双处理器上却很少发生,这与此相关吗?换句话说,这个问题是否可能与跨CPU同步实例变量有关

我有一个按钮点击事件处理程序,它更新包含表单中的私有、非共享实例变量

我还有一个System.Windows.Forms.Timer,它的勾选事件在按钮点击事件完成几秒钟后发生

我的问题是:勾选事件处理程序为什么有时(经常)看到该实例变量的前一个值?(我认为System.Windows.Forms.Timer对于实例变量是线程安全的。)

相关问题:这种情况在速度非常快的四处理器计算机上经常发生,但在速度较慢的双处理器上却很少发生,这与此相关吗?换句话说,这个问题是否可能与跨CPU同步实例变量有关

代码如下。为显示美观而修改注释约定

/* Instance variable get/set */
Public Property mode() As modetype
    Get
        Return _mode
    End Get
    Set(ByVal value As modetype)
        _mode = value
        Select Case value
            /* Lots of mode-specific processing here */
        End Select
        Debug.Assert(mode = value)
    End Set
End Property

/* Click event handler */
Private Sub btnClear_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnClear.Click
    Debug.Assert(Not (picVideo Is Nothing))
    mode = modetype.clear
End Sub

/* Tick event handler */
Private Sub tmrCapture_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tmrLiveImageCapture.Tick
    // FOLLOWING LINE is where mode should be .clear but comes up as .live instead.
    If mode = modetype.live Then
        Debug.Assert(mode = modetype.live) // Seriously? Yes.
        Try
            execute_timer_tick_stuff()
        Catch ex As Exception
            /* Shouldn't happen */
            tmrLiveImageCapture.Stop() // FIXME: can you stop a timer within its own tick event?
            MessageBox.Show("Error in live timer tick: " & ex.Message)
            Debug.Assert(Not tmrLiveImageCapture.Enabled)
        End Try
    End If
End Sub

谢谢。

为了确保同一时间只执行一个代码块,请使用SyncLock。这将防止模式值在滴答声事件期间被捕捉

您需要一个唯一的引用类型实例作为组的键:

Dim TestSyncLock As New Object()
现在一次只能执行以下一个块:;其他的则等待整个同步锁块完成,然后另一个同步锁才有机会执行

SyncLock TestSyncLock
    DoSomethingTricky()
End SyncLock

SyncLock TestSyncLock
    DoSomethingElseTricky()
End SyncLock
一次不间断地执行整个代码块称为原子操作。为您的代码尝试以下操作:

Private modeSyncLock As New Object()

/* Instance variable get/set */
Public Property mode() As modetype
    Get
        Return _mode
    End Get
    Set(ByVal value As modetype)
        /* If we have entered the tick handler's synclock, wait until it's done */
        SyncLock modeSyncLock
            _mode = value
        End SyncLock

        Select Case value
            /* Lots of mode-specific processing here */
        End Select
        Debug.Assert(mode = value)
    End Set
End Property

/* Click event handler */
Private Sub btnClear_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnClear.Click
    Debug.Assert(Not (picVideo Is Nothing))
    mode = modetype.clear
End Sub

/* Tick event handler */
Private Sub tmrCapture_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tmrLiveImageCapture.Tick
    /* If we have entered the mode set, wait until it's done before proceeding */
    SyncLock modeSyncLock
        If mode = modetype.live Then
            Debug.Assert(mode = modetype.live) // Seriously? Yes.
            Try
                execute_timer_tick_stuff()
            Catch ex As Exception
                /* Shouldn't happen */
                tmrLiveImageCapture.Stop() // FIXME: can you stop a timer within its own tick event?
                MessageBox.Show("Error in live timer tick: " & ex.Message)
                Debug.Assert(Not tmrLiveImageCapture.Enabled)
            End Try
        End If
   End SyncLock
End Sub

可能有几件事。我们能看看你的密码吗?此外,timer tick事件由windows消息触发,并与button click事件在同一线程中执行,因此这不是多线程问题,而是大量代码。我添加了一个说明性子集。谢谢你的评论。我几乎认为你的按钮事件应该是MouseUp或KeyUp。这并不是说可以解决问题,因为我认为使用
定时器
可以很容易地看到时钟的差异。只是一个想法…我觉得你的帖子没有问题。我想知道你没有发布什么。在btnClear\u Click中,在开始执行任何可能导致execute\u timer\u tick\u stuff()失败的操作之前,是否设置了模式?有没有其他语句可以改变mode(或_mode)的值而你没有发布?不,这太疯狂了,jnm2!0您将看到整个btnClear\u单击。1. _仅在模式集方法中更改模式。2.模式本身由其他未触发的事件处理程序更改。最后,我应该说mode(_mode)值在Tick事件处理程序的执行过程中会被捕获。换句话说,Tick错误地看到mode=modetype.live,然后捕获mode=modetype.clear,稍微晚一点,有点随机。最后,这并没有真正解决我的问题。。。但这是一个很好的答案,也是唯一的官方答案,所以请享受一些声誉积分。谢谢,jnm2!