VB.Net Running a task on a different thread - vb.net

I'm developing a small database management tool. I'd like the application to start up and attempt to connect to the database, but the database resides on a networked drive, so it can take a long time. During this time, the application hangs.
I'm using the below code to try and run the code to connect to the database in a different thread so that the application can load, and the database can connect separately.
Public Class Incident_Form
'DELEGATE CLASSES
Delegate Sub UpdateTable()
'DELEGATE VARIABLES
Public UpdateTableVar As UpdateTable
Private Sub Incident_Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load
I_List.DataSource = Nothing
Display_Module.Maximise_Window()
Splash_Panel.BringToFront()
System.Windows.Forms.Application.DoEvents()
UpdateTableVar = New UpdateTable(AddressOf Me.UpdateTableHandler)
Me.Invoke(Me.UpdateTableVar)
End Sub
Public Sub UpdateTableHandler() 'Handles the background work for updating I_LIST
If (Me.InvokeRequired) Then
Me.Invoke(UpdateTableVar)
Else
Dim myCon = New OleDbConnection(My.Settings.Database_Connection_String)
myCon.Open()
Dim ds As DataSet = New DataSet
Dim adapter As New OleDb.OleDbDataAdapter
Dim sql As String
sql = "SELECT [IN_REF], [Incident Name], [Date Created], [Created By] " & _
"FROM [Master_Record]"
adapter.SelectCommand = New OleDb.OleDbCommand(sql, myCon)
adapter.Fill(ds)
I_List.DataSource = ds.Tables(0)
I_List.Columns(1).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
I_List.Columns(0).HeaderText = "Reference"
I_List.Sort(I_List.Columns("Date Created"), System.ComponentModel.ListSortDirection.Descending)
myCon.Close()
End If
End Sub
The issue with the above is that although the application loads and displays the form correctly, the user still cannot interact with the form until the database finishes connecting. It's like it's running in another thread but its waiting for that thread to finish before it continues.
Is there something I'm missing or is this not the correct approach?
UPDATE 1
Thanks for the help, I've updated the code to the following and all is working correctly :)
Public Class Incident_Form
Dim ds As DataSet = New DataSet
Private Sub Incident_Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load
I_List.DataSource = Nothing
Display_Module.Maximise_Window()
Splash_Panel.BringToFront()
System.Windows.Forms.Application.DoEvents()
Try
BackgroundWorker1.RunWorkerAsync()
Catch ex As Exception
BackgroundWorker1.WorkerSupportsCancellation = True
BackgroundWorker1.CancelAsync()
End Try
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
UpdateTableHandler()
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
I_List.DataSource = ds.Tables(0)
I_List.Columns(1).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
I_List.Columns(0).HeaderText = "Reference"
I_List.Sort(I_List.Columns("Date Created"), System.ComponentModel.ListSortDirection.Descending)
End Sub
Public Sub UpdateTableHandler() 'Handles the background work for updating I_LIST
Dim myCon = New OleDbConnection(My.Settings.Database_Connection_String)
myCon.Open()
Dim adapter As New OleDb.OleDbDataAdapter
Dim sql As String
sql = "SELECT [IN_REF], [Incident Name], [Date Created], [Created By] " & _
"FROM [Master_Record]"
adapter.SelectCommand = New OleDb.OleDbCommand(sql, myCon)
adapter.Fill(ds)
myCon.Close()
End Sub

Replace your DoEvents() call with BackgroundWorker by adding it to your form.
Private Sub Incident_Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load
I_List.DataSource = Nothing
Display_Module.Maximise_Window()
Splash_Panel.BringToFront()
Try
BackgroundWorker1.RunWorkerAsync()
Catch ex As Exception
BackgroundWorker1p.WorkerSupportsCancellation = True
BackgroundWorker1.CancelAsync()
End Try
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As
System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
UpdateTableHandler()
End Sub

Related

show patients that had a certain type of diagnose

I have a patient database. In that database i have a table "diagnosetypes" and a table with dossiers with a patient that received a certain diagnose.
In my diagnose form i have a list of diagnoses and now i want to add a listbox with a filter on all patients/dossiers that had this certain diagnose when that diagnose is selected in the combobox.
this is my current code
Public Class Diagnoses
Private Sub Diagnoses_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Tbl_DossiersTableAdapter.Fill(Me.PatientenDatabaseDataSetX.tbl_Dossiers)
Me.Tbl_DiagnosesTableAdapter.Fill(Me.PatientenDatabaseDataSetX.tbl_Diagnoses)
Dim dt = Tbl_DiagnosesBindingSource
cboxDiagnose.DataSource = dt
cboxDiagnose.DisplayMember = "Diag_Type"
txtDiagnoseBeschrijving.Text = dt(0)("Diag_Type").ToString
cboxDiagnose.Focus()
End Sub
Private Sub CboxDiagnose_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles cboxDiagnose.SelectionChangeCommitted
txtDiagnoseBeschrijving.Text = DirectCast(cboxDiagnose.SelectedItem, DataRowView)("Diag_Beschrijving").ToString
End Sub
Private Sub CboxDiagnose_Click(sender As Object, e As EventArgs) Handles cboxDiagnose.Click
RefreshData()
End Sub
Private Sub BtnAddDiagnose_Click(sender As Object, e As EventArgs) Handles btnAddDiagnose.Click
FormMakeDiagnoseType.Show()
End Sub
Private Sub RefreshData()
Try
Me.Tbl_DiagnosesBindingSource.Filter = Nothing
Me.Tbl_DiagnosesTableAdapter.Fill(Me.PatientenDatabaseDataSetX.tbl_Diagnoses)
Catch ex As Exception
MsgBox("Refresh Data Error: " & ex.Message.ToString(),
MsgBoxStyle.OkOnly Or MsgBoxStyle.Information, "Add New Record Failed!")
End Try
End Sub
End Class
edit: I changed my code to look like this as a way of trying to accomplish it myself , but i won't work.
Private Sub Diagnoses_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim cn As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=F:\GoogleDrive\EINDWERK VBNET\PatientenDatabase.accdb")
cn.Open()
Dim cmmd As New OleDb.OleDbCommand("SELECT * FROM tbl_Dossiers WHERE OZ_ID.value = cboxDiagnose.text", cn)
Dim dr As OleDb.OleDbDataReader
dr = cmmd.ExecuteReader
Do While dr.Read
lboxPat_Diagcombo.Items.Add(dr("Rel_naam"))
Loop
cn.Close()
found something that works!
defined a binding source in code
then linked the listbox datasource to the binding source
then added following code :
Private Sub Onderzoeken_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Tbl_DossiersTableAdapter.Fill(Me.PatientenDatabaseDataSetX.tbl_Dossiers)
Me.Tbl_OnderzoeksTypesTableAdapter.Fill(Me.PatientenDatabaseDataSetX.tbl_OnderzoeksTypes)
Dim dt = Tbl_OnderzoeksTypesBindingSource
cboxOnderzoek.DataSource = dt
cboxOnderzoek.DisplayMember = "OZ_TypeOnderzoek"
cboxOnderzoek.ValueMember = "OZ_ID"
rtbBeschrijvingOnderzoek.Text = dt(0)("OZ_TypeOnderzoek").ToString
cboxOnderzoek.Focus()
Private Sub CboxDiagnose_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles cboxOnderzoek.SelectionChangeCommitted
rtbBeschrijvingOnderzoek.Text = DirectCast(cboxOnderzoek.SelectedItem, DataRowView)("OZ_Onderzoeksbeschrijving").ToString
Dim cn As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=F:\GoogleDrive\EINDWERK VBNET\PatientenDatabase.accdb")
cn.Open()
Dim ssql As String = "Select Rel_ID, tbl_Relaties.Rel_Naam &' ' & Rel_Voornaam as totaleNaam " &
"From tbl_Relaties INNER Join (tbl_Dossiers INNER Join tbl_DossRelatie On " &
"tbl_Dossiers.Dos_ID = tbl_DossRelatie.DR_DossID) ON tbl_Relaties.Rel_ID = tbl_DossRelatie.DR_RelID WHERE OZ_ID = " & cboxOnderzoek.SelectedValue
Dim cmmd As New OleDb.OleDbCommand(ssql, cn)
Dim dr As OleDb.OleDbDataReader
dr = cmmd.ExecuteReader
If dr.HasRows Then
Application.DoEvents()
bs_Relaties.DataSource = dr
lboxOZpatientcombo.DisplayMember = "totaleNaam"
lboxOZpatientcombo.ValueMember = "Rel_ID"
End If
cn.Close()
End Sub
since i added a binding source, the rest was easier to do:
Private Sub lboxOZpatientcombo_DoubleClick(sender As Object, e As EventArgs) Handles lboxOZpatientcombo.DoubleClick
Try
Dim MPF As New MainPatientform
MPF.display(Me, bs_Relaties.Current("rel_id"))
Catch ex As Exception
End Try
End Sub
thanks to all for new insights in this matter.

How to display data in DataGridView like flight information display

I have a program that displays data from MS Access in DataGridView by Timers
I put 2 dgvs in my Form and each one should display different data from different tables.
my dgv displays 14 rows (that's the full size of monitor!).
here is what i tried:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Timer1.Start()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
getDATA(dgv1, dgv2, Timer1, Timer2, "tab1")
End Sub
Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
getDATA(dgv2, dgv1, Timer2, Timer1, "tab2")
End Sub
Private Sub getDATA(dgv As DataGridView, vdgv As DataGridView, tm1 As Timer, tm2 As Timer, tbl As String)
Try
dgv.Visible = True
vdgv.Visible = False
If conn.State = ConnectionState.Open Then conn.Close()
Dim sqlstr As String = ""
sqlstr = "Select f1,f2,f3,f4 from " + tbl
Dim ds As New DataTable
Dim da As New OleDbDataAdapter(sqlstr, conn)
ds.Reset()
da = New OleDbDataAdapter(sqlstr, conn)
da.Fill(ds)
conn.Open()
If ds.Rows.Count = 0 Then
dgv.Rows.Clear()
Else
dgv.Rows.Clear()
dgv.Rows.Add(ds.Rows.Count)
For s = 0 To ds.Rows.Count - 1
dgv.Rows(s).Cells(0).Value = ds.Rows(s).Item("f1")
dgv.Rows(s).Cells(1).Value = ds.Rows(s).Item("f2")
dgv.Rows(s).Cells(2).Value = ds.Rows(s).Item("f3")
dgv.Rows(s).Cells(3).Value = ds.Rows(s).Item("f4")
Next s
End If
dgv.ClearSelection()
conn.Close()
tm1.Stop()
tm2.Start()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
This code is work fine, but sometimes one of the tables contains more than 14 rows!
how can i display the rest of rows in specific DGV?
should i use another Timer?

No New Row Entry Added to Access Backend

so I made this code which is supposed to update the Delivery table in my MS Access database. The code runs fine and even says that data entry is successful, but upon checking the database file no new row entry is made.
Public Class NewDelivery
Dim ds As New DataSet
Dim da As OleDb.OleDbDataAdapter
Dim con As New OleDb.OleDbConnection
Public Shared stxtboxsupsel As TextBox
Public Shared supnum As String
Public Shared dgvitems As DataGridView
Private Sub NewDelivery_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DateTimePicker1.Format = DateTimePickerFormat.Custom
DateTimePicker1.CustomFormat = "MM/dd/yyyy"
End Sub
Private Function OpenDBConnection()
If My.Settings.DatabaseLoc = "" Then
Dim directory As String = My.Computer.FileSystem.SpecialDirectories.MyDocuments
Return "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=" & directory & "\IE156.mdb"
Else
Return "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=" & My.Settings.DatabaseLoc
End If
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
My.Forms.ManageInventory.Show()
Me.Close()
End Sub
Private Sub btnSelSupp_Click(sender As Object, e As EventArgs) Handles btnSelSupp.Click
My.Forms.SelectSupplier.Show()
stxtboxsupsel = txtboxsupsel
End Sub
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
con.ConnectionString = OpenDBConnection()
con.Open()
Dim sql As String = "INSERT INTO Delivery(ItemPurchDate,SupNum) VALUES (#ItemPurchDate,#SupNum)"
Dim cmd As New OleDb.OleDbCommand(sql, con)
cmd.Parameters.AddWithValue("#ItemPurchDate", DateTimePicker1.Text)
cmd.Parameters.AddWithValue("#SupNum", supnum)
con.Close()
Me.Close()
MsgBox("New Delivery Recorded")
End Sub
The Delivery Table has 3 columns namely ItemPurchNum (Primary Key and Autonumber), ItemPurchDate(date/time) and SupNum(Number and has a many to one relationship with SupNum from my Supplier table).
I had no trouble adding new rows in my other forms following the similar code. Any thoughts on why it won't add a new row? Thank you in advance!
thanks for your help. Noticed that I skipped a line cmd.ExecuteNonQuery(), and now it works!

HOW TO FILL COMBO BOX IN VB.NET

I have a code to fill my combo box but every time i close the form the list is being doubled, if i have a list from my database of English, Mathematics, Science after i close the form and open it again the list showing is now English, Mathematics, Science, English, Mathematics, Science
HERE IS THE CODE,
Call OpenDB()
cmd.CommandText = "select * from Subject"
cmd.Connection = conn
dr = cmd.ExecuteReader
While dr.Read()
cmbSubject.Items.Add(dr("Subject Name"))
End While
dr.Close()
Call CloseDB()
The problem is not in the method you are using to bind the combobox. in each time it binds that's why you are getting duplicate records in the database. to avoid this please clear the combobox before each bind, like the following:
Call OpenDB()
cmbSubject.Items.Clear ' extra statement added to clear the item collection
cmd.CommandText = "select * from Subject"
cmd.Connection = conn
dr = cmd.ExecuteReader
While dr.Read()
cmbSubject.Items.Add(dr("Subject_Name"))
End While
dr.Close()
Call CloseDB()
If you need an alternate method for binding the combobox i will suggest you binding with Dataset
following is the example code for this :
Dim SQL As String= "select Subject_Name,Subject_code from Subject"
Dim adapter As New OdbcDataAdapter(SQL, conn) '<-- This function will Retrieve Data and Return as Dataset together with table name
Dim myData As New DataSet
myData.Fill(lobjDataSet, tblName)
cmbSubject.DataSource = ds_myData
cmbSubject.DataMember = "Subject"
cmbSubject.DataTextField = "Subject_Name"
cmbSubject.DataValueField = "Subject_code"
cmbSubject.DataBind()
myData .Dispose()
Public Class frmRegistration
Dim obj As New Entity.Registration
Dim bus As New Business.Registration
Private Sub BtnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnSave.Click
BindingSource1.EndEdit()
bus.Save(obj)
RefreshGrid()
MsgBox("Saved.")
End Sub
Sub RefreshGrid()
Dim dt1 As DataTable = bus.Select()
BindingSource2.DataSource = dt1
DataGridView1.AllowUserToAddRows = False
DataGridView1.DataSource = BindingSource2
End Sub
Private Sub Registration_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
RefreshGrid()
NewItem()
End Sub
Private Sub BtnNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnNew.Click
NewItem()
End Sub
Sub ResetDis()
BindingSource1.DataSource = obj
End Sub
Sub NewItem()
obj = New Entity.Registration
ResetDis()
End Sub
Private Sub BindingSource2_CurrentChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BindingSource2.CurrentChanged
obj = New Entity.Registration(CType(Me.BindingSource2.Current, DataRowView).Row)
ResetDis()
End Sub
End Class

Application with two forms is not showing

I am creating a form application using Visual Studio Express VB 2008 and SQL server 2008. I have two forms. When the program start is not showing me any form. What is to be done that I could use two forms as one program. For example, in one form I want to insert data type state, city .. and the other to use the same information for something else. But like I said, my first step is to see both forms in one program. What should I do to make it work
Imports System.Data.Sql
Imports System.Data.SqlClient
' This is my main form called form1 and through it I want to call a form called Country. Belonging to the same project. How to call a form ,,country,, that I could use
Public Class Form1
Dim objDS As New DataSet
Dim objDA As New SqlDataAdapter
Public Sqlcon As New SqlConnection With {.connectionString = "server=XXX\MSSQL2008;database=TEST;Trusted_Connection=True;"}
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If hasConnection() = True Then
MessageBox.Show("uspijesno povezano sa bazom")
End If
getSelc()
End Sub
Public Function hasConnection() As Boolean
Try
Sqlcon.Open()
Sqlcon.Close()
Return True
Catch ex As Exception
MessageBox.Show("Niste povezani sa bazom")
Return False
End Try
End Function
Public Function selc()
Dim objDS = New DataSet
Dim objDA As New SqlDataAdapter
Sqlcon.Close()
Sqlcon.Open()
Dim exCommand As String = ""
Dim myCommand As New SqlCommand
Dim commitTransaction = Sqlcon.BeginTransaction
Try
myCommand = New SqlCommand("EXECUTE " & "regionSelect" & " '" & txtID.EditValue & "', '" & txtShortN.EditValue & "', N'" & txtRegion.EditValue & "', '" & txtStatus.EditValue & "'", Sqlcon)
myCommand.Transaction = commitTransaction
objDA.SelectCommand = myCommand
objDA.Fill(objDS)
commitTransaction.Commit()
Sqlcon.Close()
MessageBox.Show("Podaci su uspijesno poslati")
Catch ex As Exception
MessageBox.Show(ex.Message)
commitTransaction.Rollback()
End Try
End Function
Private Sub SimpleButton3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnInsert.Click
'insert()
End Sub
Private Sub btnConfirm_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConfirm.Click
getSelc()
End Sub
Public Function getSelc()
objDS = New DataSet
Dim com As New SqlCommand
Sqlcon.Close()
Sqlcon.Open()
GridControl1.DataSource = Nothing
Try
com = New SqlCommand("EXECUTE rS '" & txtID.Text & " ' , ' " & txtRegion.Text & "' , '" & txtShortN.Text & "', ' " & txtStatus.Text & " ' ", Sqlcon)
'com = New SqlCommand("SELECT * FROM tblRegion", Sqlcon)
objDA.SelectCommand = com
objDA.Fill(objDS)
com.CommandType = CommandType.StoredProcedure
GridControl1.DataSource = objDS.Tables(0)
objDA.Dispose()
com.Dispose()
Sqlcon.Close()
MessageBox.Show("Im here")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
'GridControl1.DataSource = Nothing
'objDS.Tables(0).Rows.Clear()
End Function
Private Sub SimpleButton4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SimpleButton4.Click
getSelc()
Dim newRow As DataRow
newRow = objDS.Tables(0).NewRow
newRow.Item(0) = txtID.EditValue
newRow.Item(1) = txtShortN.EditValue
newRow.Item(2) = txtRegion.EditValue
newRow.Item(3) = txtStatus.EditValue
objDS.Tables(0).Rows.Add(newRow)
End Sub
Private Sub SimpleButton3_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SimpleButton3.Click
End Sub
Private Sub SimpleButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SimpleButton1.Click
Country.Show() ' => Is this a good way, and is there any better way and more efficient
End Sub
End Class
You cannot load more than one form on Application Startup. You have to load any one form first then show others from its Form_Load event.
Private Sub StartupForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim form2 As New Form2
form2.Show()
Dim form3 As New Form3
form3.Show()
End Sub
Or you can load forms manually on Button Click.
Set the Form1 as a StartupForm from the Project Property Window.
Now, Add a button in your first form button1 and write down some code to display another form.
Private Sub button1_Click(sender As Object, e As EventArgs) Handles button1.Click
Dim form2 As New Form2
form2.Show()
End Sub
Another one is calling main method. For that you need to assign Main method in your Project Property Window
Module mainModule
Sub Main()
Dim form2 As New Form2
form2.Show()
Dim form3 As New Form3
form3.ShowDialog()
End Sub
End Module