Cross-thread operation not valid: VB.net I'm a noob.. - vb.net

I have two codes here separately it works but when i put it together i get the error "Cross-thread operation not valid". i tried to search the web how to solve this, i just don't get how to apply it in my codes.
Cross-Thread operation not valid VB.NET
http://forums.asp.net/t/1467258.aspx?Error+Cross+thread+operation+not+valid+Control+Listbox1+accessed+from+a+thread+other+than+the+thread+it+was+created+on+
CODE 1 use to Screen Shot my PANEL control.
Private Sub CaptureSHOT(ctrl As Control, fileName As String)
Dim bounds As Rectangle = ctrl.Bounds
Dim pt As Point = ctrl.PointToScreen(bounds.Location)
Dim bitmap As New Bitmap(bounds.Width, bounds.Height)
Using g As Graphics = Graphics.FromImage(bitmap)
g.CopyFromScreen(New Point(pt.X - ctrl.Location.X, pt.Y - ctrl.Location.Y), Point.Empty, bounds.Size)
End Using
bitmap.Save(fileName, ImageFormat.Png)
End Sub
CODE 2 use to call my "CaptureShot" Function via timer when the FORM loads.
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
MyBase.OnLoad(e)
Dim tmr As New System.Timers.Timer()
tmr.Interval = 2000
tmr.Enabled = True
tmr.Start()
AddHandler tmr.Elapsed, AddressOf OnTimedEvent
End Sub
Private Delegate Sub CloseFormCallback()
Private Sub CloseForm()
If InvokeRequired Then
Dim d As New CloseFormCallback(AddressOf CloseForm)
Invoke(d, Nothing)
Else
Close()
End If
End Sub
Private Sub OnTimedEvent(ByVal sender As Object, ByVal e As ElapsedEventArgs)
CaptureSHOT(Panel1, "D:\SC\" & erk & ".png")
CloseForm()
End Sub
The Error i'm getting

Geez you're all hostile today haha kidding aside thanks to Enigmativity and varocarbas strict lecture i notice that i already have a "Private Delegate Sub" for my CloseFormCallback() and i keep getting an error because i was adding another "Private Delegate Sub" for my "CaptureShot" Function. now i just add the "CaptureSHOT(Panel1, "D:\SC\" & erk & ".png")" to my Private Delegate Sub CloseFormCallback(). and it works!
Private Delegate Sub CloseFormCallback()
Private Sub CloseForm()
If InvokeRequired Then
Dim d As New CloseFormCallback(AddressOf CloseForm)
Invoke(d, Nothing)
Else
CaptureSHOT(Panel1, "D:\SC\" & erk & ".png")
Close()
End If
End Sub

Related

BackgroundWorker UI and Progress issues

So I've been fiddling with this for a while and I don't know if I'm not understanding how the BackgroundWorker works and/or I'm using it wrong or if I'm missing something.
Basically what I'm trying to do is call a BackgroundWorker from a DragDrop function where the user can drop a set of images into the form. The BackgroundWorder then copies the images to a temp location thumbnails are pulled and turned into PictureBoxes and the PictureBoxes are added to a collection. Once the BackgroundWorker is completed the function runs to add all the picture boxes to the form.
All of this is working properly except the progress. The progress function doesn't like to fire until near the end (after almost all the pictures have been copied) during this time the UI is locked (which I'm sure is why the progress function isn't firing) I just can't figure out why the UI is locking.
I've stepped through the code and the ReportProgress method is being called ever loop but the ProgressReported function isn't called until near the end.
HELP! LOL
this is the ControlClass for my copying and creating thumbnails
Imports System.ComponentModel
Imports System.IO
Namespace ThumbnailViewer
Public Class ThumbnailControl
Inherits FlowLayoutPanel
Private ImageExtensions As List(Of String) = New List(Of String) From {".JPG", ".JPE", ".BMP", ".GIF", ".PNG"}
Private tempStoragePath As String = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & "\tempPhotos"
Private WithEvents bkWPhotos As New BackgroundWorker
Public Property iThumbList As List(Of PictureBox)
Public Property sImageList As List(Of String(,))
Private PopupPrg As PopUpProgress.PopUpProgressControl
Public Sub New()
Me.AutoScroll = True
Me.AllowDrop = True
Me.DoubleBuffered = True
iThumbList = New List(Of PictureBox)()
sImageList = New List(Of String(,))()
AddHandler Me.DragDrop, AddressOf ThumbnailViewerControl_DragDrop
AddHandler Me.DragEnter, AddressOf ThumbnailViewerControl_DragEnter
If Not Directory.Exists(tempStoragePath) Then Directory.CreateDirectory(tempStoragePath)
bkWPhotos.WorkerReportsProgress = True
bkWPhotos.WorkerSupportsCancellation = True
End Sub
Public Sub BackGroundWorker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bkWPhotos.DoWork
AddImage(e.Argument)
End Sub
Public Sub BackGroundWorkder_Progress(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) Handles bkWPhotos.ProgressChanged
PopupPrg.SetProgress(e.ProgressPercentage)
End Sub
Public Sub BackGroundWorker_Complete(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles bkWPhotos.RunWorkerCompleted
For Each i As PictureBox In iThumbList
Me.Controls.Add(i)
Next
PopupPrg.Destory()
Me.Cursor = Cursors.Default
End Sub
Public Sub AddImage(ByVal files As String())
Dim fImage As Image
Dim prg As Integer = 0
For Each f As String In files
If ImageExtensions.Contains(Path.GetExtension(f).ToUpperInvariant()) Then
bkWPhotos.ReportProgress(prg)
fImage = Image.FromFile(f)
File.Copy(f, tempStoragePath & "\" & Path.GetFileName(f), True)
sImageList.Add({{tempStoragePath & "\" & Path.GetFileName(f), fImage.Size.Width, fImage.Size.Height}})
Dim t As PictureBox = MakeThumbnail(fImage)
prg = prg + 1
GC.GetTotalMemory(True)
End If
Next
End Sub
Public Function MakeThumbnail(ByVal inImage As Image) As PictureBox
Dim thumb As PictureBox = New PictureBox()
thumb.Size = ScaleImage(inImage.Size, 200)
thumb.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
thumb.SizeMode = PictureBoxSizeMode.Zoom
AddHandler thumb.MouseEnter, AddressOf thumb_MouseEnter
AddHandler thumb.MouseLeave, AddressOf thumb_MouseLeave
AddHandler thumb.DoubleClick, AddressOf thumb_DoubleClick
thumb.Image = inImage.GetThumbnailImage(thumb.Width - 2, thumb.Height - 2, Nothing, New IntPtr())
iThumbList.Add(thumb)
Return thumb
End Function
Private Sub thumb_DoubleClick(ByVal sender As Object, ByVal e As EventArgs)
Dim previewForm As Form = New Form()
Dim index As Integer = Me.Controls.GetChildIndex(CType(sender, PictureBox))
Dim img As Image = Image.FromFile(sImageList(index)(0, 0))
previewForm.FormBorderStyle = FormBorderStyle.SizableToolWindow
previewForm.MinimizeBox = False
previewForm.Size = ScaleImage(img.Size, Screen.GetWorkingArea(Me).Height / 4 * 3)
previewForm.StartPosition = FormStartPosition.CenterScreen
Dim view As PictureBox = New PictureBox()
view.Dock = DockStyle.Fill
view.Image = Image.FromFile(sImageList(index)(0, 0))
view.SizeMode = PictureBoxSizeMode.Zoom
previewForm.Controls.Add(view)
previewForm.ShowDialog()
End Sub
Private Sub thumb_MouseLeave(ByVal sender As Object, ByVal e As EventArgs)
CType(sender, PictureBox).Invalidate()
End Sub
Private Sub thumb_MouseEnter(ByVal sender As Object, ByVal e As EventArgs)
Dim rc = (CType(sender, PictureBox)).ClientRectangle
rc.Inflate(-2, -2)
ControlPaint.DrawBorder((CType(sender, PictureBox)).CreateGraphics(), (CType(sender, PictureBox)).ClientRectangle, Color.Red, ButtonBorderStyle.Solid)
ControlPaint.DrawBorder3D((CType(sender, PictureBox)).CreateGraphics(), rc, Border3DStyle.Bump)
End Sub
Private Sub ThumbnailViewerControl_DragEnter(ByVal sender As Object, ByVal e As DragEventArgs)
If e.Data.GetDataPresent(DataFormats.FileDrop) Then e.Effect = DragDropEffects.Copy Else e.Effect = DragDropEffects.None
End Sub
Private Sub ThumbnailViewerControl_DragDrop(ByVal sender As Object, ByVal e As DragEventArgs)
If e.Data.GetDataPresent(DataFormats.FileDrop) Then
Dim files As String() = CType(e.Data.GetData(DataFormats.FileDrop), String())
Me.Cursor = Cursors.WaitCursor
PopupPrg = New PopUpProgress.PopUpProgressControl(Me, files.Count)
bkWPhotos.RunWorkerAsync(files)
End If
End Sub
Public Function ScaleImage(ByVal oldImage As Size, ByVal TargetHeight As Integer) As Size
Dim NewHeight As Integer = TargetHeight
Dim NewWidth As Integer = NewHeight / oldImage.Height * oldImage.Width
NewHeight = NewWidth / oldImage.Width * oldImage.Height
Return New Size(NewWidth, NewHeight)
End Function
End Class
End Namespace
.... FacePalm.. I figured it out. Apparently during my testing (before I decided to use this control and a background worker, I had added another drag drop function in another area of my code that was being called first. It was taking all the dragged images and turning them into Image data types. The rest of the function was commented out which is why I didn't notice it before because I was only stepping though the classes functions not the functions in the main UI. but it makes perfect sense now, the backgroundworker and the UI function were kicking off at the same time but while the UI thread was processing the Image data typing the report progress calls were stacking up.
After removing that secondary function it works exactly as it should, UI remains fully functional Images and PictureBoxes are processed in the background and the Progressbar updates properly and remains functional as well.

VB.NET: Code runs without error, but does not add item to listbox

I've got this embedded CMD on my form which I created using another person's code and everything works right. Inside one of the Private Subs (that seems to run every time a new line is written in the CMD output textbox), I've got a line which adds a item to a listbox (listboxs name is txtPlayerList) on another form labelled Status.
When this area of the code runs, it doesn't throw up any errors (and if I put a msgbox() on the same line, the msgbox() works). If I put the add to listbox line on form_load it works perfectly?
Here is my code, I've included everything from that form just in case (it is in the third sub from the top with the asterisks and comment "Get players and maybe other stuff as well"
Imports System.IO
Public Class Console
Public WithEvents MyProcess As Process
Private Delegate Sub AppendOutputTextDelegate(ByVal text As String)
Public LastLine As String
Public LastLineFormatted As String
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim LocalpathParent As String = Application.StartupPath() + "\MCserver"
'loads embed cmd
Me.AcceptButton = ExecuteButton
MyProcess = New Process
With MyProcess.StartInfo
.FileName = "CMD.EXE"
.UseShellExecute = False
.CreateNoWindow = True
.RedirectStandardInput = True
.RedirectStandardOutput = True
.RedirectStandardError = True
.WorkingDirectory = LocalpathParent
End With
MyProcess.Start()
MyProcess.BeginErrorReadLine()
MyProcess.BeginOutputReadLine()
AppendOutputText("Process Started at: " & MyProcess.StartTime.ToString)
'Resize with parent mdi container. Needs to be anchored & StartPosition = manual in properties
Me.WindowState = FormWindowState.Maximized
End Sub
Private Sub MyProcess_ErrorDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles MyProcess.ErrorDataReceived
AppendOutputText(vbCrLf & "Error: " & e.Data)
End Sub
Private Sub MyProcess_OutputDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles MyProcess.OutputDataReceived
AppendOutputText(vbCrLf & e.Data)
'*****************************************
'Get Players and maybe other stuff as well
'*****************************************
LastLine = Me.OutputTextBox.Lines.Last
If Status.ServerStarted = True Then
If Me.LastLine.Contains(" joined the game") Then
LastLineFormatted = Me.LastLine
LastLineFormatted = LastLineFormatted.Replace(" joined the game", "")
'***THIS LINE BELOW WORKS IN FORM LOAD, BUT NOT HERE FOR SOME REASON???***
Status.txtPlayersList.Items.Add(LastLineFormatted)
MsgBox("add lastlineformatted")
ElseIf Me.LastLine.Contains(" left the game") Then
LastLineFormatted = Me.LastLine
LastLineFormatted = LastLineFormatted.Replace(" left the game", "")
Status.txtPlayersList.Items.Remove(LastLineFormatted)
End If
End If
End Sub
Private Sub ExecuteButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExecuteButton.Click
MyProcess.StandardInput.WriteLine(InputTextBox.Text)
MyProcess.StandardInput.Flush()
InputTextBox.Text = ""
End Sub
Private Sub AppendOutputText(ByVal text As String)
If OutputTextBox.InvokeRequired Then
Dim myDelegate As New AppendOutputTextDelegate(AddressOf AppendOutputText)
Try
Me.Invoke(myDelegate, text)
Catch
End Try
Else
Try
OutputTextBox.AppendText(text)
Catch
End Try
End If
End Sub
End Class
EDIT: Below is the code I have for form1 per request
'code
Public Class Form1
Public Localpath As String
Public Downloadpath As String
Public LocalpathParent As String
'when this form is closing, send stop to console to make sure it has closed and saved
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Console.MyProcess.StandardInput.WriteLine("stop") 'send an EXIT command to the Command Prompt
Application.Exit()
End
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'load stuff in background n stuff
Me.Show()
Me.Focus()
Configure.Show()
Configure.Hide()
Status.Show()
Status.Hide()
Console.Show()
Console.Hide()
End Sub
'CONSOLE.form
Private Sub ConsoleToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles ConsoleToolStripMenuItem1.Click
'Hide all forms
Status.Hide()
Configure.Hide()
'Shown Form that you want to load
Console.Opacity = 100
Console.Show()
WindowState = FormWindowState.Normal
Console.MdiParent = Me
Console.OutputTextBox.SelectionStart = Console.OutputTextBox.Text.Length
Console.OutputTextBox.ScrollToCaret()
End Sub
'STATUS.form
Private Sub StatusToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles StatusToolStripMenuItem1.Click
'hide all forms
Console.Hide()
Configure.Hide()
'Show Form that you want to load
Status.Opacity = 100
Status.Show()
WindowState = FormWindowState.Maximized
Configure.Size = Me.Size
Status.MdiParent = Me
End Sub
'CONFIGURE.form
Private Sub ConfigurationToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles ConfigurationToolStripMenuItem1.Click
'hide all forms
Status.Hide()
Console.Hide()
'Show form that you want to load
Configure.Opacity = 100
Configure.Show()
WindowState = FormWindowState.Maximized
Configure.Size = Me.Size
Configure.MdiParent = Me
End Sub
End Class
'code
It seems that your original code to create an embeded CMD window was interfering with the code to update the listbox in another mdi child. After finding another way to embed a cmd console, and some fiddling around, It seems to be working Ok. I haven't been able to test pure server output yet though.
THere have been quite a few changes to the code that are too big to post here, but the Alternative embedded CMD is this.
Place this in general form declarations
'command prompt variables
Private strResults As String
Private intStop As Integer
Private swWriter As System.IO.StreamWriter
Friend thrdCMD As System.Threading.Thread
Private Delegate Sub cmdUpdate()
Private uFin As New cmdUpdate(AddressOf UpdateText)
Public WithEvents procCMDWin As New Process
This in your form_load Sub
thrdCMD = New System.Threading.Thread(AddressOf Prompt)
thrdCMD.IsBackground = True
thrdCMD.Start()
and these declarations within your form Class
Private Sub Prompt()
AddHandler procCMDWin.OutputDataReceived, AddressOf CMDOutput
AddHandler procCMDWin.ErrorDataReceived, AddressOf CMDOutput
procCMDWin.StartInfo.RedirectStandardOutput = True
procCMDWin.StartInfo.RedirectStandardInput = True
procCMDWin.StartInfo.CreateNoWindow = True
procCMDWin.StartInfo.UseShellExecute = False
procCMDWin.StartInfo.FileName = "cmd.exe"
procCMDWin.StartInfo.WorkingDirectory = LocalpathParent
procCMDWin.Start()
procCMDWin.BeginOutputReadLine()
swWriter = procCMDWin.StandardInput
Do Until (procCMDWin.HasExited)
Loop
procCMDWin.Dispose()
End Sub
Private Sub UpdateText()
OutputTextBox.Text += strResults
OutputTextBox.SelectionStart = OutputTextBox.TextLength - 1
InputTextBox.Focus()
intStop = OutputTextBox.SelectionStart
OutputTextBox.ScrollToCaret()
If OutputTextBox.Lines.Count > 2 Then
LastLine = OutputTextBox.Lines.ElementAt(OutputTextBox.Lines.Count - 2)
If Status.ServerStarted = True Then
'get element 1 of split
If LastLine.Contains(" joined the game") Then
LastLineFormatted = ExtractName(LastLine, " joined the game")
'If listlineformatted.contains(Players.allitems) then do
Status.txtPlayersList.Items.Add(LastLineFormatted)
Status.Show()
ElseIf Me.LastLine.Contains(" left the game") Then
LastLineFormatted = ExtractName(LastLine, " left the game")
'If listlineformatted.contains(Players.allitems) then do
Status.txtPlayersList.Items.Remove(LastLineFormatted)
MsgBox("remove lastlineformatted")
End If
End If
End If
End Sub
Private Function ExtractName(unformattedString As String, stringToRemove As String) As String
Dim temp As String = Split(unformattedString, "Server]")(1).ToString
ExtractName = temp.Replace(stringToRemove, "")
End Function
Private Sub CMDOutput(ByVal Sender As Object, ByVal OutputLine As DataReceivedEventArgs)
strResults = OutputLine.Data & Environment.NewLine
Invoke(uFin)
End Sub

VB Thread Timer Update UI

I made a small program that allows for individual timer countdowns for each button clicked. (e.g. clicking on button 1 will start a countdown for button 1 whilst updating the text on the button itself to reflect the time remaining.)
My worry now is that I'm not sure how well my program would work in the long run. Here's a snippet of the code.
Private Sub depBtn_Clicked(sender As Button, e As EventArgs)
If sender.BackColor = Color.Green Then
Dim depRow() As Data.DataRow
Dim id As String = sender.Name
depRow = DepartmentDataSet.Departments.Select("ID Like '" & id & "'")
sender.BackColor = Color.Red
Dim timerBtn As New DepartmentTimer(sender, depRow(0)("Duration"), depRow(0)("ID"))
Dim TimerDelegate As New System.Threading.TimerCallback(AddressOf TimerTask)
Dim TimerItem As New System.Threading.Timer(TimerDelegate, timerBtn, 0, 1000)
timerBtn.timerRef = TimerItem
End If
End Sub
Private Delegate Sub TimerTaskDelegate(ByVal obj As Object)
Private Sub TimerTask(ByVal obj As Object)
If Me.InvokeRequired() Then
Me.Invoke(New TimerTaskDelegate(AddressOf TimerTask), obj)
Else
Dim depTimer As DepartmentTimer = DirectCast(obj, DepartmentTimer)
depTimer.countDown()
If depTimer.duration = -1 Then
depTimer.finish()
depTimer.timerRef.Dispose()
End If
End If
End Sub
I have read and also experienced that if I were to update on the UI thread directly from the timer callback the whole program would crash. So I ended up using a delegate in accordance to here http://tech.xster.net/tips/invoke-ui-changes-across-threads-on-vb-net/.
Is this a proper way of doing it or am I doing anything redundant/inefficient?
Also when I dispose of the Timer object. How would I go about cleaning up the DepartmentTimer class instance (timerBtn)? The button can be activated again once the timer runs out so I'm afraid that the instances would build up if I don't take care of them properly.
Thanks in advance for any help.
Since you're not actually doing anything with the Timer except immediately Invoking back to the main UI thread, you might as well just use one System.Windows.Forms.Timer and update them all in the same handler.
Something like:
Public Class Form1
Private timers As New List(Of DepartmentTimer)
Private WithEvents Tmr As New System.Windows.Forms.Timer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Tmr.Interval = 1000
Tmr.Start()
End Sub
Private Sub depBtn_Clicked(sender As Button, e As EventArgs)
If sender.BackColor = Color.Green Then
Dim depRow() As Data.DataRow
Dim id As String = sender.Name
depRow = DepartmentDataSet.Departments.Select("ID Like '" & id & "'")
sender.BackColor = Color.Red
timers.Add(New DepartmentTimer(sender, depRow(0)("Duration"), depRow(0)("ID")))
End If
End Sub
Private Sub Tmr_Tick(sender As Object, e As EventArgs) Handles Tmr.Tick
For i As Integer = timers.Count - 1 To 0 Step -1
Dim depTimer As DepartmentTimer = timers(i)
depTimer.countDown()
If depTimer.duration = -1 Then
depTimer.finish()
timers.RemoveAt(i)
End If
Next
End Sub
End Class

Using SqlDependency with named Queues in vb.net to populate the datagridview each time there is a change in database

Am developing an interface that needs to get data from the database and post to main system in real time.ie when a transcation is initiated in need to hit the main system in realtime for responce fo futher proccessing. i am creating an interface for the application which uses sql server.
i am trying to use the sqldependancy with the following code
Option Strict On
Option Explicit On
Imports System.Data.SqlClient
Imports System.Security.Permissions
mports System.ComponentModel
Public Class Home
Private Sub Home_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'BillPaymentsDataSet.Transactions_Temp' table. You can move, or remove it, as needed.
Me.Transactions_TempTableAdapter.Fill(Me.BillPaymentsDataSet.Transactions_Temp)
End Sub
Private Function GetConnectionString() As String
Return My.Settings.BillPaymentsConnectionString
End Function
Sub Initialization()
Dim con As New SqlConnection(My.Settings.BillPaymentsConnectionString)
SqlDependency.Start(My.Settings.BillPaymentsConnectionString)
End Sub
Private Function CanRequestNotifications() As Boolean
Dim permission As New SqlClientPermission( _
PermissionState.Unrestricted)
Try
permission.Demand()
Return True
Catch ex As Exception
Return False
End Try
End Function
Private Sub GetData()
BillPaymentsDataSet = Nothing
dt = New DataTable()
BillPaymentsDataSet.Clear()
SqlDependency.Stop(GetConnectionString())
SqlDependency.Start(GetConnectionString())
command.Notification = Nothing
If con Is Nothing Then
con = New SqlConnection(GetConnectionString())
End If
Dim dependency As New SqlDependency(command)
AddHandler dependency.OnChange, AddressOf dependency_OnChange
con.Open()
Using Transactions_TempTableAdapter As New SqlDataAdapter(command)
Me.Transactions_TempTableAdapter.Fill(Me.BillPaymentsDataSet.Transactions_Temp)
Me.DataGridView1.DataSource = BillPaymentsDataSet.Transactions_Temp
End Using
End Sub
Private Sub UserMantainanceToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles UserMantainanceToolStripMenuItem.Click
UserMantain.Show()
End Sub
Private Sub dependency_OnChange( _
ByVal sender As Object, ByVal e As SqlNotificationEventArgs)
Dim changeCount As Integer = 0
Const statusMessage As String = _
"{0} changes have occurred."
Dim i As ISynchronizeInvoke = CType(Me, ISynchronizeInvoke)
If i.InvokeRequired Then
' Create a delegate to perform the thread switch
Dim tempDelegate As New OnChangeEventHandler( _
AddressOf dependency_OnChange)
Dim args() As Object = {sender, e}
' Marshal the data from the worker thread
' to the UI thread.
i.BeginInvoke(tempDelegate, args)
Return
End If
' Remove the handler since it's only good
' for a single notification
Dim dependency As SqlDependency = _
CType(sender, SqlDependency)
RemoveHandler dependency.OnChange, _
AddressOf dependency_OnChange
' At this point, the code is executing on the
' UI thread, so it is safe to update the UI.
changeCount += 1
Me.Label1.Text = String.Format(statusMessage, changeCount)
' Add information from the event arguments to the list box
' for debugging purposes only.
With Me.ListBox1.Items
.Clear()
.Add("Info: " & e.Info.ToString())
.Add("Source: " & e.Source.ToString())
.Add("Type: " & e.Type.ToString())
End With
' Reload the dataset that's bound to the grid.
GetData()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
End Sub
End Class

UI freezes on different thread

I've tried elsewhere but nothing came of it. Basically i want the image to show up in the picturebox.
My code:
Dim ScreenReceiverClient As New TcpClient
Dim ScreenReceiverServer As New TcpListener(ScreenReceiverPort)
Dim ScreenReceiverListening As New Thread(AddressOf ScreenListen)
Dim GetScreen As New Thread(AddressOf ReceiveScreen)
Private Sub ReceiveScreen()
While ScreenReceiverClient.Connected = True
Call New Action(AddressOf ChangeImage).BeginInvoke(Nothing, Nothing)
End While
End Sub
Private Sub ChangeImage()
Dim bf As New BinaryFormatter
PictureBox1.Image = bf.Deserialize(ScreenReceiverClient.GetStream)
End Sub
Private Sub ScreenListen()
While ScreenReceiverClient.Connected = False
ScreenReceiverServer.Start()
ScreenReceiverClient = ScreenReceiverServer.AcceptTcpClient
End While
GetScreen.Start()
End Sub
ChangeImage() is supposed to be called on the UI thread instead of the ScreenReceiverListening thread, but the UI just freezes. Please help me!
You need to call the Method asynchronously:
http://msdn.microsoft.com/de-de/library/2e08f6yc(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1
Another easy way is, to use a timer:
Private Sub ScreenListen()
While ScreenReceiverClient.Connected = False
ScreenReceiverServer.Start()
ScreenReceiverClient = ScreenReceiverServer.AcceptTcpClient
End While
t1.Interval = 1
t1.Start()
End Sub
Private WithEvents t1 As Windows.Forms.Timer
Private Sub t1_Tick(sender As Object, e As EventArgs) Handles t1.Tick
t1.Stop()
ReceiveScreen()
End Sub