异步 GetFiles 并写入 Sqlite 数据库
Async GetFiles and Write into Sqlite Database
我有一个软件,我想在其中获取列表中的所有文件,然后将它们写入 sqlite 数据库。但是,当我调用该方法时,它会阻塞主 UI,即使我尝试执行一些等待任务也是如此。我究竟做错了什么?这是我的代码:
这是 window 加载时我调用方法来获取文件列表并将其放入我正在创建的 sqlite 数据库中。
Private Async Function MainWindow_Loaded() As Task
Try
InitializeComponent()
Await CreateFileList()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
End Function
Create the filelist and put it into sqlite database function. It should be async but something wrong with it.
Private Async Function CreateFileList() As Task
Try
lblState1.Content = "Create File List"
If Directory.Exists(System.AppDomain.CurrentDomain.BaseDirectory & "filelist") Then
Directory.Delete(System.AppDomain.CurrentDomain.BaseDirectory & "filelist", True)
End If
Dim tasks As List(Of Task) = New List(Of Task)()
Dim t As Task = Task.Run(Sub()
For Each path In Directory.GetFiles(System.AppDomain.CurrentDomain.BaseDirectory, "*.*", SearchOption.AllDirectories)
FilesList.Add(path)
Next
End Sub)
tasks.Add(t)
Task.WaitAll(tasks.ToArray)
Database.DbCreator.createDbFile("filelist", "filelist.db3")
Database.DbCreator.createDbConnection("filelist\filelist.db3")
If Database.DbCreator.checkIfTableExist("filelist") = False Then
Dim create_table As String = String.Empty
create_table &= "CREATE TABLE IF NOT EXISTS filelist ("
create_table &= "id INTEGER PRIMARY KEY NOT NULL,"
create_table &= "filepath TEXT NOT NULL,"
create_table &= "filesize TEXT NOT NULL DEFAULT 0,"
create_table &= "needstobedone INTEGER NOT NULL DEFAULT 0,"
create_table &= "todownload INTEGER NOT NULL DEFAULT 0)"
Await Database.DbCreator.SqlNewQuery(create_table)
End If
Dim i As Integer = 1
For Each file As String In FilesList
If Not file.Contains("/Updates/") Or Not file.Contains("/filelist/") Or Not file.Contains("/lic/") Then
varPercent = Math.Round(i / FilesList.Count * 100)
Dim filesize As Long = New FileInfo(file).Length
Dim InsertQuery As String = ""
InsertQuery &= "INSERT INTO filelist (filepath, filesize) VALUES "
InsertQuery &= String.Format("('{0}','{1}')", file.Replace(System.AppDomain.CurrentDomain.BaseDirectory, ""), filesize)
Await Database.DbCreator.SqlNewQuery(InsertQuery)
i = i + 1
End If
Next
Database.DbCreator.closeDbConnection("filelist\filelist.db3")
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
End Function
My Database Creators functions, it should be async as well. Any suggestion on this way?
Namespace Database
Public Class DbCreator
Public Shared dbConnection As SQLiteConnection
Public Shared command As New SQLiteCommand
Public Shared sqlCommand As String
Public Shared dbPath As String = System.AppDomain.CurrentDomain.BaseDirectory
Public Shared dbFilePath As String
Public Shared Sub createDbFile(dir As String, name As String)
Try
If Not String.IsNullOrEmpty(name) AndAlso Not Directory.Exists(dbPath & dir) Then Directory.CreateDirectory(dbPath & dir)
dbFilePath = dbPath & "\" & dir & "\" & name
If Not File.Exists(dbFilePath) Then
SQLiteConnection.CreateFile(dbFilePath)
End If
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
End Sub
Public Shared Function createDbConnection(name) As String
Dim strCon As String = String.Format("Data Source={0};", System.AppDomain.CurrentDomain.BaseDirectory & name)
Try
dbConnection = New SQLiteConnection(strCon)
dbConnection.Open()
command = dbConnection.CreateCommand()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
Return strCon
End Function
Public Shared Function DbConnect(name) As SQLiteConnection
Dim strCon As String = String.Format("Data Source={0};", System.AppDomain.CurrentDomain.BaseDirectory & name)
Try
dbConnection = New SQLiteConnection(strCon)
dbConnection.Open()
command = dbConnection.CreateCommand()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
Return dbConnection
End Function
Public Shared Function closeDbConnection(name) As String
Dim strCon As String = String.Format("Data Source={0};", System.AppDomain.CurrentDomain.BaseDirectory & name)
Try
dbConnection = New SQLiteConnection(strCon)
dbConnection.Close()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Hiba: " & ex.ToString)
End Try
Return strCon
End Function
Public Shared Async Function SqlNewQuery(command As String) As Task
Try
sqlCommand = command
Await executeQuery(sqlCommand)
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
End Function
Public Shared Function checkIfTableExist(ByVal tableName As String) As Boolean
Dim result As Object = Nothing
command.CommandText = ""
Try
command.CommandText = "SELECT name FROM sqlite_master WHERE name='" & tableName & "'"
result = command.ExecuteScalar()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Hiba: " & ex.ToString)
End Try
Return If(result IsNot Nothing AndAlso result.ToString() = tableName, True, False)
End Function
Public Shared Async Function executeQuery(ByVal sqlCommand As String) As Task
Try
Dim triggerCommand As SQLiteCommand = dbConnection.CreateCommand()
triggerCommand.CommandText = sqlCommand
Await triggerCommand.ExecuteNonQueryAsync()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
End Function
Public Shared Function checkIfTableContainsData(ByVal tableName As String) As Boolean
Dim result As Object = Nothing
Try
command.CommandText = "SELECT count(*) FROM " & tableName
result = command.ExecuteScalar()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Hiba: " & ex.ToString)
End Try
Return If(Convert.ToInt32(result) > 0, True, False)
End Function
End Class
End Namespace
Task.WaitAll(tasks.ToArray)
会阻塞你的UI线程,你应该等待异步方法的结果。没有 Directory.GetFilesAsync 方法,所以最终你应该编写自己的代码。
Dim filesList As List(Of String) = Await Task(Of List(Of String)).Run(
Function()
Dim files As List(Of String) = New List(Of String)()
For Each path In Directory.GetFiles(System.AppDomain.CurrentDomain.BaseDirectory, "*.*", SearchOption.AllDirectories)
files.Add(path)
Next
Return files
End Function)
我有一个软件,我想在其中获取列表中的所有文件,然后将它们写入 sqlite 数据库。但是,当我调用该方法时,它会阻塞主 UI,即使我尝试执行一些等待任务也是如此。我究竟做错了什么?这是我的代码:
这是 window 加载时我调用方法来获取文件列表并将其放入我正在创建的 sqlite 数据库中。
Private Async Function MainWindow_Loaded() As Task
Try
InitializeComponent()
Await CreateFileList()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
End Function
Create the filelist and put it into sqlite database function. It should be async but something wrong with it.
Private Async Function CreateFileList() As Task
Try
lblState1.Content = "Create File List"
If Directory.Exists(System.AppDomain.CurrentDomain.BaseDirectory & "filelist") Then
Directory.Delete(System.AppDomain.CurrentDomain.BaseDirectory & "filelist", True)
End If
Dim tasks As List(Of Task) = New List(Of Task)()
Dim t As Task = Task.Run(Sub()
For Each path In Directory.GetFiles(System.AppDomain.CurrentDomain.BaseDirectory, "*.*", SearchOption.AllDirectories)
FilesList.Add(path)
Next
End Sub)
tasks.Add(t)
Task.WaitAll(tasks.ToArray)
Database.DbCreator.createDbFile("filelist", "filelist.db3")
Database.DbCreator.createDbConnection("filelist\filelist.db3")
If Database.DbCreator.checkIfTableExist("filelist") = False Then
Dim create_table As String = String.Empty
create_table &= "CREATE TABLE IF NOT EXISTS filelist ("
create_table &= "id INTEGER PRIMARY KEY NOT NULL,"
create_table &= "filepath TEXT NOT NULL,"
create_table &= "filesize TEXT NOT NULL DEFAULT 0,"
create_table &= "needstobedone INTEGER NOT NULL DEFAULT 0,"
create_table &= "todownload INTEGER NOT NULL DEFAULT 0)"
Await Database.DbCreator.SqlNewQuery(create_table)
End If
Dim i As Integer = 1
For Each file As String In FilesList
If Not file.Contains("/Updates/") Or Not file.Contains("/filelist/") Or Not file.Contains("/lic/") Then
varPercent = Math.Round(i / FilesList.Count * 100)
Dim filesize As Long = New FileInfo(file).Length
Dim InsertQuery As String = ""
InsertQuery &= "INSERT INTO filelist (filepath, filesize) VALUES "
InsertQuery &= String.Format("('{0}','{1}')", file.Replace(System.AppDomain.CurrentDomain.BaseDirectory, ""), filesize)
Await Database.DbCreator.SqlNewQuery(InsertQuery)
i = i + 1
End If
Next
Database.DbCreator.closeDbConnection("filelist\filelist.db3")
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
End Function
My Database Creators functions, it should be async as well. Any suggestion on this way?
Namespace Database
Public Class DbCreator
Public Shared dbConnection As SQLiteConnection
Public Shared command As New SQLiteCommand
Public Shared sqlCommand As String
Public Shared dbPath As String = System.AppDomain.CurrentDomain.BaseDirectory
Public Shared dbFilePath As String
Public Shared Sub createDbFile(dir As String, name As String)
Try
If Not String.IsNullOrEmpty(name) AndAlso Not Directory.Exists(dbPath & dir) Then Directory.CreateDirectory(dbPath & dir)
dbFilePath = dbPath & "\" & dir & "\" & name
If Not File.Exists(dbFilePath) Then
SQLiteConnection.CreateFile(dbFilePath)
End If
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
End Sub
Public Shared Function createDbConnection(name) As String
Dim strCon As String = String.Format("Data Source={0};", System.AppDomain.CurrentDomain.BaseDirectory & name)
Try
dbConnection = New SQLiteConnection(strCon)
dbConnection.Open()
command = dbConnection.CreateCommand()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
Return strCon
End Function
Public Shared Function DbConnect(name) As SQLiteConnection
Dim strCon As String = String.Format("Data Source={0};", System.AppDomain.CurrentDomain.BaseDirectory & name)
Try
dbConnection = New SQLiteConnection(strCon)
dbConnection.Open()
command = dbConnection.CreateCommand()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
Return dbConnection
End Function
Public Shared Function closeDbConnection(name) As String
Dim strCon As String = String.Format("Data Source={0};", System.AppDomain.CurrentDomain.BaseDirectory & name)
Try
dbConnection = New SQLiteConnection(strCon)
dbConnection.Close()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Hiba: " & ex.ToString)
End Try
Return strCon
End Function
Public Shared Async Function SqlNewQuery(command As String) As Task
Try
sqlCommand = command
Await executeQuery(sqlCommand)
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
End Function
Public Shared Function checkIfTableExist(ByVal tableName As String) As Boolean
Dim result As Object = Nothing
command.CommandText = ""
Try
command.CommandText = "SELECT name FROM sqlite_master WHERE name='" & tableName & "'"
result = command.ExecuteScalar()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Hiba: " & ex.ToString)
End Try
Return If(result IsNot Nothing AndAlso result.ToString() = tableName, True, False)
End Function
Public Shared Async Function executeQuery(ByVal sqlCommand As String) As Task
Try
Dim triggerCommand As SQLiteCommand = dbConnection.CreateCommand()
triggerCommand.CommandText = sqlCommand
Await triggerCommand.ExecuteNonQueryAsync()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Error: " & ex.ToString)
End Try
End Function
Public Shared Function checkIfTableContainsData(ByVal tableName As String) As Boolean
Dim result As Object = Nothing
Try
command.CommandText = "SELECT count(*) FROM " & tableName
result = command.ExecuteScalar()
Catch ex As Exception
WriteLog(DateTime.Now.ToString & " Hiba: " & ex.ToString)
End Try
Return If(Convert.ToInt32(result) > 0, True, False)
End Function
End Class
End Namespace
Task.WaitAll(tasks.ToArray)
会阻塞你的UI线程,你应该等待异步方法的结果。没有 Directory.GetFilesAsync 方法,所以最终你应该编写自己的代码。
Dim filesList As List(Of String) = Await Task(Of List(Of String)).Run(
Function()
Dim files As List(Of String) = New List(Of String)()
For Each path In Directory.GetFiles(System.AppDomain.CurrentDomain.BaseDirectory, "*.*", SearchOption.AllDirectories)
files.Add(path)
Next
Return files
End Function)