如何从另一个类和线程调用WindowsFormsSynchronizationContext可能是我自己的愚蠢,但我已经到处搜索,无法理解。
如果我将worker和代码放在Form1的主体中,它确实有用。
Form1:
Public Shared UIContext As WindowsFormsSynchronizationContext
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
UIContext = WindowsFormsSynchronizationContext.Current
Dim StartClock As New SendtoUI
End Sub
Public Sub updatelable(incomingText As String)
Label1.Text = incomingText
End Sub
测试类:
Public Class SendtoUI
Private lastUpdated As DateTime = DateTime.Now
Private backgroundTimer As System.Timers.Timer
Public Sub New()
backgroundTimer = New Timers.Timer(1000)
AddHandler backgroundTimer.Elapsed, New System.Timers.ElapsedEventHandler(AddressOf backgroundTimer_Elapsed)
backgroundTimer.Start()
End Sub
Private Sub backgroundTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
lastUpdated = DateTime.Now
Form1.UIContext.Post(Sub()
Form1.updatelable(lastUpdated.ToLongTimeString())
End Sub, Nothing)
End Sub
End Class
基于以上,
Label1.Text = incomingText
该行已执行,但标签未更新。可能很简单,但我很难过。
感谢您的帮助!
-TD
好的,我明白了,感谢Jimi,我更新了我的最终结果,并希望它可以帮助别人!
简单form1如下:
Imports System.Threading
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim TestTHreadUI As New ThreadedBackground(SynchronizationContext.Current, New SendOrPostCallback(AddressOf UpdateUI))
End Sub
Public Sub UpdateUI(incomingText As Object)
Label1.Text = incomingText.ToString
End Sub
End Class
ThreadedBackground类:
Imports System.Threading
Public Class ThreadedBackground
Private backgroundTimer As System.Timers.Timer
Public Sub New(UIContext As SynchronizationContext, UpdateAddress As SendOrPostCallback)
SyncContext = UIContext
SyncCallback = UpdateAddress
backgroundTimer = New Timers.Timer(1000)
AddHandler backgroundTimer.Elapsed, New System.Timers.ElapsedEventHandler(AddressOf backgroundTimer_Elapsed)
backgroundTimer.Start()
End Sub
'SynchronizationContext used for Posting
Public Property SyncContext As System.Threading.SynchronizationContext
'The Object Callback address to call
Public Property SyncCallback As System.Threading.SendOrPostCallback
Private Sub backgroundTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
'SyncContext.Post(SyncCallback, CType(DateTime.Now.ToLongTimeString, Object)) ' using passed in SendOrPostCallback(SyncCallback)
SyncContext.Post(New SendOrPostCallback(Sub() Form1.UpdateUI(DateTime.Now.ToLongTimeString)), Nothing) ' Not using SendOrPostCallback(SyncCallback), Direct call to form1 Sub using lambda
'SyncContext.Post(New SendOrPostCallback(Sub() Form1.Label1.Text = DateTime.Now.ToLongTimeString), Nothing) ' Not using SendOrPostCallback(SyncCallback), Direct call to form1 Control using lambda
End Sub
End Class
答案 0 :(得分:0)
我会考虑在你的班级中避免对特定对象(本例中为Form)的静态引用
一种方法是为您的类添加一些可以保存该引用的属性。
您的代码可以编辑为:
cnxn = pyodbc.connect(cnxn_str)
cursor = cnxn.cursor()
#Sample select query
print 'Testing db connection...'
cursor.execute("SELECT @@version;")
row = cursor.fetchone()
while row:
print row[0]
row = cursor.fetchone()
您的班级有新属性:
Imports System.Threading
Public Class Form1
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim StartClock As New SendtoUI
StartClock.SyncContext = System.Windows.Forms.WindowsFormsSynchronizationContext.Current
StartClock.SyncCallback = New System.Threading.SendOrPostCallback(AddressOf Me.updatelable)
End Sub
'Delegate signature
'Public Delegate Sub SendOrPostCallback(state As Object)
Public Sub updatelable(incomingText As Object)
Label1.Text = incomingText.ToString
End Sub
End Class