How to make each form it's own thread and able to update? - vb.net

I am have three(4 counting the main one) threads in my application(chat app) and I want to put each form into it's own thread(one thread does not need a form so it is irrelevant). The 2 forms I am working with are clocks with a local digital font included. The problem is that threadb will start and run, but threadc will remain as the text LABEL1 and not change at all to: MM/dd/yyyy hh:mm:ss tt. I am wondering how to get these threads to work together.
Here is the thread code(creating at beginning of porgram, this is from sub official_start):
threadb = New Threading.Thread(AddressOf form3threadsub)
threadc = New Threading.Thread(AddressOf form4threadsub)
threadb.IsBackground = False
threadc.IsBackground = False
threadb.Start()
threadc.Start()
Here is the code for the thread subs:
Private Sub form3threadsub()
Dim first As Boolean = False
Do
System.Threading.Thread.Sleep(100)
If first = False Then
form3.ShowDialog()
first = True
End If
form3.Label1.Text = DateTime.UtcNow.ToString("MM/dd/yyyy hh:mm:ss tt")
form3.Update()
Loop
End Sub
Private Sub form4threadsub()
Dim first As Boolean = False
Do
System.Threading.Thread.Sleep(100)
If first = False Then
Form4.ShowDialog()
first = True
End If
Form4.Label1.Text = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss tt")
Form4.Update()
Loop
End Sub
Here is the button2 click:
Dim clicked As Boolean = True
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If clicked Then
threadb.Suspend()'obsolete
threadc.Suspend()'obsolete
Button2.Text = "Resume Clocks"
clicked = False
Else
threadb.Resume()'obsolete
threadc.Resume()'obsolete
Button2.Text = "Pause Clocks"
clicked = True
End If
End Sub

I think I found my working solution. I took the extra forms out and replaced them with labels on the main form. Each label is it's own thread and updates accordingly.

Related

WebBrowser won't fire DocumentCompeted event or print

So I've been looking around for a solution to this for a little over a week to no avail. I have a program that needs to be able to print htm(l) files and I'm having a terrible time getting it to comply.
This is the code I'm using at the moment:
Private Sub HtmlPrinterLaunch(i As Integer)
'Dim htmlWBPrinter As New WebBrowser()
'AddHandler htmlWBPrinter.DocumentCompleted, New WebBrowserDocumentCompletedEventHandler(AddressOf HtmlPrinter)
'htmlWBPrinter.Visible = True
'htmlWBPrinter.ScriptErrorsSuppressed = False
'htmlWBPrinter.Show()
''frmHTMLPrint.wbPrintHtml.AllowNavigation = True
''AddHandler frmHTMLPrint.wbPrintHtml.DocumentCompleted, AddressOf HtmlPrinter
''frmHTMLPrint.wbPrintHtml.Visible = False
''frmHTMLPrint.wbPrintHtml.Navigate("file:///" & IO.Path.GetFullPath(_prints(i).SourcePathFileName))
''Application.Run(frmHTMLPrint)
''Dim appPath As String = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase)
''Dim reportPath As String = Path.Combine(appPath, Path.GetFileName(_prints(i).SourcePathFileName))
''htmlWBPrinter.Url = New Uri(reportPath) 'New Uri(Path.Combine("file:///", reportPath)) 'New Uri("file://" & IO.Path.GetFullPath(_prints(i).SourcePathFileName))
'htmlWBPrinter.Url = (New Uri(Path.Combine("file:///" & IO.Path.GetFullPath(_prints(i).SourcePathFileName))))
'While ((htmlWBPrinter.DocumentText = ""))
' Thread.Sleep(10000)
'End While
'htmlWBPrinter.ShowPrintDialog()
'' htmlWBPrinter.Dispose()
Dim wb As New WebBrowser
AddHandler wb.DocumentCompleted, Sub() If wb.ReadyState = WebBrowserReadyState.Complete Then wb.Print()
wb.ScriptErrorsSuppressed = True
Dim url As New Uri(Path.Combine("file:///" & IO.Path.GetFullPath(_prints(i).SourcePathFileName)))
wb.Navigate(url)
End Sub
Private Sub HtmlPrinter(sender As Object, e As WebBrowserDocumentCompletedEventArgs)
state = 4
Dim wbPrinter As WebBrowser = CType(sender, WebBrowser)
wbPrinter.Print()
wbPrinter.Dispose()
'frmHTMLPrint.BeginInvoke(New Action(Sub() frmHTMLPrint.Close()))
End Sub
As you can see I have a couple attempts in there (kept some older code that sort of worked but I'd rather not us it as I kept getting pop ups)
Some likely related issues:
-the WebBrowser state stays in loading (1)
-the Url never updates with the file:///path even if I pass it directly
So to put it in brief, my in code WebBrowser control won't hit the DocumentCompleted event, nor will it print out files. I need this code to print documents with no input from the user. What am I missing here?
Edit:
So I've messed around with this some more. I have the webbrowser control on its own form and I can get it to load/print when called from the main thread, but I'm having no luck invoking it. My current code for invocation:
If wbPrintHtml.InvokeRequired Then
If url.SourcePathFileName = "about:blank" Then
wbPrintHtml.Invoke(CType(Sub()
wbPrintHtml.Navigate(url.SourcePathFileName)
End Sub, MethodInvoker))
Else
wbPrintHtml.Invoke(CType(Sub()
wbPrintHtml.Navigate("file:///" & url.SourcePathFileName)
End Sub, MethodInvoker))
End If
Else
If url.SourcePathFileName = "about:blank" Then
wbPrintHtml.Navigate(url.SourcePathFileName)
Else
wbPrintHtml.Navigate("file:///" & url.SourcePathFileName)
End If
End If
I finally got this to work as intended. It's not the prettiest thing in the world, but it functions, and I'm ok with that.
Public Class frmHTMLPrint
Public Shared formHandle As frmHTMLPrint
Private Sub wbPrintHtml_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles wbPrintHtml.DocumentCompleted
Dim wbPrinter As WebBrowser = CType(sender, WebBrowser)
If wbPrinter.ReadyState = WebBrowserReadyState.Complete AndAlso Not wbPrinter.Url.ToString() = "about:blank" Then
wbPrinter.Print()
End If
End Sub
Shared Function setURL(url As Reporter.ReportServer.PrintMessageType) As Boolean
If formHandle.wbPrintHtml.InvokeRequired Then
If url.SourcePathFileName = "about:blank" Then
formHandle.wbPrintHtml.Invoke(CType(Sub()
formHandle.wbPrintHtml.Navigate(url.SourcePathFileName)
End Sub, MethodInvoker))
Else
formHandle.wbPrintHtml.Invoke(CType(Sub()
formHandle.wbPrintHtml.Navigate("file:///" & url.SourcePathFileName)
End Sub, MethodInvoker))
End If
Dim wbReady As WebBrowserReadyState
formHandle.wbPrintHtml.Invoke(CType(Sub()
wbReady = formHandle.wbPrintHtml.ReadyState
End Sub, MethodInvoker))
While ((Not wbReady = WebBrowserReadyState.Complete))
Application.DoEvents()
formHandle.wbPrintHtml.Invoke(CType(Sub()
wbReady = formHandle.wbPrintHtml.ReadyState
End Sub, MethodInvoker))
End While
Return wbReady = 4
Else
If url.SourcePathFileName = "about:blank" Then
formHandle.wbPrintHtml.Navigate(url.SourcePathFileName)
Else
formHandle.wbPrintHtml.Navigate("file:///" & url.SourcePathFileName)
End If
While ((Not formHandle.wbPrintHtml.ReadyState = WebBrowserReadyState.Complete))
Application.DoEvents()
End While
Return formHandle.wbPrintHtml.ReadyState = 4
End If
End Function
Private Sub frmHTMLPrint_Load() Handles Me.Load
InitializeComponent()
Dim wbInitializer As New Reporter.ReportServer.PrintMessageType
formHandle = Me
wbInitializer.SourcePathFileName = "about:blank"
setURL(wbInitializer)
End Sub
End Class

Textbox not updating after thread abort

I have a thread which is executing a sub and within a sub I am updating the textbox during a "Do while" loop is in progress. I then created a cancel button to abort the thread.
When the button is clicked then the thread is aborted but the textbox (Status_Txtbox.Text) doesn't get updated with the message "Parsing is terminated". I tried to do the debug and I see the code is executed perfectly and if condition for thread.isalive satisfies but not sure why the textbox doesn't get updated with the message.
Any idea how to update the textbox once thread is aborted ?
Dim thrd1 As Thread
Private Sub Parse_Btn_2G_Click(sender As Object, e As RoutedEventArgs) Handles Parse_Btn_2G.Click
Parse_Btn_2G.IsEnabled = False
Scan_Btn_2G.IsEnabled = False
cancel_Btn_2G.IsEnabled = True
Dim start As DateTime = DateTime.Now
Dim elapsedtime As Double
Dim action As Action
thrd1 = New Thread(Sub()
ButtonClickWork.DoWork()
action = Sub()
Status_Txtbox.Text = "Parsing Data, Please wait..."
End Sub
Me.Dispatcher.Invoke(action)
End Sub)
thrd1.Start()
elapsedtime = (DateTime.Now.Subtract(start).TotalSeconds) / 60
elapsedtime = Math.Round(elapsedtime, 2)
Status_Txtbox.Text = " Managed Objects in XML, total time elapsed is" & elapsedtime
End Sub
Private Sub Cancel_Btn_2G_Click(sender As Object, e As RoutedEventArgs) Handles cancel_Btn_2G.Click
Try
If cancel_Btn_2G.IsEnabled = True Then
If MsgBox("Do you really want to exit Parsing?", vbYesNo) = MsgBoxResult.Yes Then
Parse_Btn_2G.IsEnabled = True
Scan_Btn_2G.IsEnabled = True
cancel_Btn_2G.IsEnabled = False
thrd1.Abort()
thrd1.Join()
If thrd1.IsAlive = False Then
Status_Txtbox.Text = "Parsing is terminated"
End If
End If
End If
Catch ex As ThreadAbortException
Status_Txtbox.Text = "Parsing is terminated"
End Try
End Sub

IndexOutOfRangeException error when DataGridView header is clicked

Iam trying to get DataGridView rowIndex and set it to textbox and all is well with this code
Private Sub dgv_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgv.CellContentClick
isitxt(e.RowIndex)
btnInsert.Enabled = False
btnUpdate.Enabled = True
btnDelete.Enabled = True
End Sub
and
Sub isitxt(ByVal x As Integer)
txtIDBarang.Text = dgv.Rows(x).Cells(0).Value
txtNamaBarang.Text = dgv.Rows(x).Cells(1).Value
cbJenisBarang.Text = dgv.Rows(x).Cells(2).Value
numHargaBeli.Value = dgv.Rows(x).Cells(3).Value
numHargaJual.Value = dgv.Rows(x).Cells(4).Value
End Sub
But i got IndexOutOfRangeException when i clicked on Column Header. how can i handle it ?
Note, that if you use CellContentClick, the code will be executed only if the user actually aims at text content of a cell. Usually a CellClick is makes more sense.
As for your code, you can debug and see, what's in "x", when you get an error - I guess "-1"... You can handle it then. However, the reason for this should not be in your code above.
You can also set SelectionMode = FullRowSelect and do it following way:
Private Sub dgv_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgv.CellClick
isitxt(Me.dgv.selectedRows(0).index)
btnInsert.Enabled = False
btnUpdate.Enabled = True
btnDelete.Enabled = True
End Sub
Unless you want to handle the cells separately, users usually prefer the FullRowSelect mode.

Managing `CheckBox_Checked` Event without an infinite loop

I know this seems like an easy fix, but I am having trouble. I have a CheckBox, when checked, I remove the data source of a DataGridView on my Windows Form and remove the ReadOnly properties of a few Textbox.
I know the CheckedChanged event will send my code into an infinite loop, but I cannot figure out which event would handle this change without changing the CheckedState each time. I have tried using Click, MouseClick, and CheckStateChanged events with no luck.
This is my current code:
Private Sub chkManual_MouseClick(sender As Object, e As EventArgs) Handles chkManual.MouseClick
If Not Me.chkManual.Checked Then
Me.chkManual.Checked = False
Me.cbRegion.SelectedIndex = -1
Me.txtIssueDate.ReadOnly = True
Me.txtCasenum.ReadOnly = True
Me.txtCommnum.ReadOnly = True
Exit Sub
Else
Me.dgDataEntry.DataSource = Nothing
Me.cbRegion.SelectedIndex = -1
Me.txtIssueDate.ReadOnly = False
Me.txtCasenum.ReadOnly = False
Me.txtCommnum.ReadOnly = False
ClearForm()
frmPDF.Hide()
Exit Sub
End If
End Sub
Properties of CheckBox: AutoCheck = True, Checked = False, and CheckState = Unchecked
I have looked into these already:
CheckBox_Checked event
Is there a simpler way to process check boxes?
CheckBox reverts to checked after being unchecked
How to check if a checkboxes state has changed
How can I prevent an assignment statement to CheckBox.Checked from raising the CheckChanged event?
http://www.vbforums.com/showthread.php?758455-CheckBox-code-got-stuck-in-an-infinite-loop-can-not-unchecked-it
EDIT
It helps if your ClearForm() sub doesn't change the CheckedState of your CheckBox back to False every time. Thank you #Visual Vincent for pointing out the obvious. Nothing is wrong with the code, changed the EventHandler to CheckedChanged
Final code (so simple):
Private Sub chkManual_CheckedChanged(sender As Object, e As EventArgs) Handles chkManual.CheckedChanged
If Me.chkManual.Checked Then
Me.dgDataEntry.DataSource = Nothing
Me.cbRegion.SelectedIndex = -1
Me.txtIssueDate.ReadOnly = False
Me.txtCasenum.ReadOnly = False
Me.txtCommnum.ReadOnly = False
ClearForm()
frmPDF.Hide()
Else
Me.cbRegion.SelectedIndex = -1
Me.txtIssueDate.ReadOnly = True
Me.txtCasenum.ReadOnly = True
Me.txtCommnum.ReadOnly = True
End If
End Sub
I'm not sure if you want the CheckBox, when Checked, to Uncheck again automatically or not!?...seems like a weird interface.
At any rate, if you want something to occur when the Check state changes:
Private Sub chkManual_CheckedChanged(sender As Object, e As EventArgs) Handles chkManual.CheckedChanged
If chkManual.Checked Then
Debug.Print("Checked")
Me.dgDataEntry.DataSource = Nothing
Me.cbRegion.SelectedIndex = -1
Me.txtIssueDate.ReadOnly = False
Me.txtCasenum.ReadOnly = False
Me.txtCommnum.ReadOnly = False
ClearForm()
frmPDF.Hide()
Else
Debug.Print("UnChecked")
Me.cbRegion.SelectedIndex = -1
Me.txtIssueDate.ReadOnly = True
Me.txtCasenum.ReadOnly = True
Me.txtCommnum.ReadOnly = True
End If
End Sub
You can uncheck the checkbox without an infinite loop like this:
Private Sub chkManual_CheckedChanged(sender As Object, e As EventArgs) Handles chkManual.CheckedChanged
Static counter As Integer
If chkManual.Checked Then
counter = counter + 1 ' just to show we're not in an infinite loop...
Debug.Print("Checked " & counter) ' just to show we're not in an infinite loop...
chkManual.Checked = False
Else
Debug.Print("UnChecked")
End If
End Sub
Not sure why you'd want to do that...seems like that would basically be a "reset" button as it couldn't stay in a checked state...
Can you remove the code that changes the checkbox state? Ex:
Me.chkManual.Checked = False
The box will check or uncheck without your code having to do it, and the event will only throw once.
I think the easiest way is to remove event listener before handling checkbox checked state. Use try-finally block to ensure that checkbox event listener is always set back.
Try
RemoveHandler chkManual AddressOf chkManual_MouseClick
Me.chkManual.Checked = False
...
Finally
AddHandler chkManual AddressOf chkManual_MouseClick
End Try

delay or stop execution for some time in vb.net

hi i want to delay the execution of code for some time on buton click i cal a func named chance() ..
which gets called after a picture box.image change .. bt the image does not change nd func chance() starts ... i want delay in chance() after the picture is changed ... thus help me ..
code
Private Sub p11_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles p11.Click
row = 1
col = 1
chck() 'function which returns hit var value
p11.Enabled = False
If hit = 1 Then
p11.Image = Image.FromFile("G:\visual progs\BATTLESHIP\hit.png")
ElseIf hit = 0 Then
p11.Image = Image.FromFile("G:\visual progs\BATTLESHIP\miss.png")
lblstatus.Text = "COMPUTER's TURN ... PLEASE WAIT ... "
chance() ' func begins
End If
End Sub
Function chance()
***'here i want a pause for 2 sec***
Dim z As Int16 = 1
While z = 1
row = mnw.Next(9) + 1
col = mnw.Next(9) + 1
If c(row, col) = False Then
c(row, col) = True
z = 0
End If
End While
chck1() ' checks for hit or miss for computer
changepic() 'changes pic hit or miss for computer
Return 0
End Function
To get a pause of 2 seconds, you simply need to suspend the thread by doing this:
Thread.Sleep(2000)
Although you can use Thread.Sleep to introduce a delay, it has generally undesirable side-effects, in particular the form and its controls become unresponsive. A better way is to use a timer - that way the form is still responsive (e.g. you can move it around).
Also, you seem to be a little unsure of where to use a Sub and where to use a Function. A Sub does something, and a Function is used to return a value, ideally with no side-effects.
You could try this with a new Windows Forms project and just a PictureBox named p11 and a Label named lblStatus:
Imports System.IO
Public Class Form1
Dim tim As Windows.Forms.Timer
Const GAMEPATH As String = "G:\visual progs\BATTLESHIP\"
Dim HitImgFile As String = Path.Combine(GAMEPATH, "hit.png")
Dim MissImgFile As String = Path.Combine(GAMEPATH, "miss.png")
Private Sub SetUpTimer()
tim = New Timer
tim.Interval = 2000 ' milliseconds
tim.Enabled = False
AddHandler tim.Tick, AddressOf Chance
End Sub
Private Sub Chance(sender As Object, e As EventArgs)
tim.Enabled = False
' your code for the computer's turn goes here
lblStatus.Text = "Your turn"
p11.Enabled = True
End Sub
Private Function IsHitByUser() As Boolean
' placeholder code for the actual check
If Rnd() < 0.5 Then
Return True
End If
Return False
End Function
Private Sub DoComputerTurn()
lblStatus.Text = "COMPUTER's TURN ... PLEASE WAIT ... "
p11.Enabled = False
tim.Enabled = True
End Sub
Private Sub p11_Click(sender As Object, e As EventArgs) Handles p11.Click
If IsHitByUser() Then
p11.Image = Image.FromFile(HitImgFile)
lblStatus.Text = "HIT"
Else
p11.Image = Image.FromFile(MissImgFile)
DoComputerTurn()
End If
End Sub
Private Sub StartGame()
lblStatus.Text = "Your turn"
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
SetUpTimer()
StartGame()
End Sub
End Class