.net 如何使用TPL同时读取多个文件
我想创建一个Winforms应用程序来读取48个文本文件,每个文件只有一行逗号分隔的值,并用每个文件的结果填充MySQL数据库和DataGridView 通过搜罗SO和谷歌,以及数月的反复试验,我所能想到的最好结果如下:.net 如何使用TPL同时读取多个文件,.net,vb.net,multithreading,task-parallel-library,.net,Vb.net,Multithreading,Task Parallel Library,我想创建一个Winforms应用程序来读取48个文本文件,每个文件只有一行逗号分隔的值,并用每个文件的结果填充MySQL数据库和DataGridView 通过搜罗SO和谷歌,以及数月的反复试验,我所能想到的最好结果如下: Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click BackgroundWorker1.RunWorkerAsync() End Sub Private S
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
UpdateMcs()
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
Me.MainTableAdapter.Fill(Me.MyDataSet.main)
If stopPolling = False Then BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub UpdateMcs()
Dim tasks As New List(Of Task)
For Each row As DataRow In MyDataSet.main
If row("model") = "A" Then
tasks.Add(Task.Factory.StartNew(Sub()
Try
Dim Path As String = "\\" & row("server_ip") & "\mc_data\mc_" & Format(row("mc_num"), "00") & ".txt"
Dim lines() As String = File.ReadAllLines(Path)
Dim data As String = lines(0)
Dim state As New stateTableAdapter
Try
state.UpdateByIP(data, row("ip"))
Console.WriteLine("{0}: {1}", row("ip"), "Success")
Catch ex As Exception
Console.WriteLine("{0}: {1}", row("ip"), ex.Message)
End Try
Catch ex As Exception
Console.WriteLine("{0}: {1}", row("ip"), ex.Message)
End Try
End Sub))
End If
Next
Task.WaitAll(tasks.ToArray())
End Sub
但我想做的是让每台机器在完成时更新DB和刷新UI,而不是等待其余的完成
我已经尝试过为每台机器生成单独的线程,但这导致了非常多的错误行为和锁定的UI等,所以不是很成功
我还应该注意到,我还有另外39台机器将使用一个API进行数据轮询,该API也需要单独运行
有没有更有效的方法来解决这个问题
其中一个主要问题是,如果一台机器(或承载数据文件的服务器)由于某种原因处于脱机状态建立事实的时间与轮询联机机器的时间之比可能为500毫秒与10秒,因此让所有联机机器等待脱机机器意味着DB更新频率受到性能最差轮询的严重限制
任何关于更好的学习方法和资源的建议都是非常受欢迎的 这是异步IO的一个很好的例子。同步IO所需的线程数量导致了问题,所以让我们使用异步IO来删除它们 看起来几乎所有的时间都花在了
ReadAllLines
上,所以让它异步
在C#中大致可以这样看:
这几乎就是你需要做的所有改变
请注意,
Task.WaitAll
将阻止它运行的线程。如果您想避免在此处使用wait
(wait Task.whall(tasks)
)。您错过了lambda的async
。在这种情况下是否使用Task.Run
在很短的时间内“阻止”线程池线程?@Cameron(达到第一次等待所需的时间,应接近零)。你可以省略它,但这似乎是一个更安全的选择,因为我认为他是在UI线程上运行此功能的。ReadAllLinesAsync
是自定义函数吗?我找不到任何关于它的提及…?我试图编写自己的ReadAllLinesAsync
函数,但我无法让它工作。另外,我应该使用BackgroundWorker.ProcessC吗挂起事件,在读取每个文件时触发DB&UI更新,或者是否有更好的解决方案?
tasks.Add(Task.Run(async () => {
var data = await File.ReadAllLinesAsync(...);
//rest of code here
});