첫 번째 타이머는 여기에 나와 있으므로 쉽게 이동하십시오. 이론적으로 두 개의 OleDBDataAdapter.Fill 호출을 별도의 스레드에서 동시에 실행할 수 있습니까? 아니면 근본적으로 결함이 있습니까?동시 OleDbDataAdapter.Fill 별도의 스레드에서 호출?
2 개의 버튼과 2 개의 데이터 그람저가있는 양식을 고려하십시오. 각 단추를 클릭하면 채워진 데이터 테이블을 반환하는 메서드를 호출하고이를 datagridview 중 하나에 할당하는 Async \ Await \ Task.Run 패턴을 사용하여 작업자 스레드가 시작됩니다. 첫 번째 스레드의 .Fill은 완료하는 데 30 초가 걸립니다. 두 번째 스레드의 .Fill은 완료하는 데 1 초가 걸립니다. 개별적으로 실행되면 두 단추가 모두 예상대로 작동합니다.
그러나 처음 작업자 스레드 (채우기 30 초)를 실행 한 다음 두 번째 스레드 (1 초 채우기)를 시작하면 첫 번째 .Fill 호출이 완료 될 때까지 두 번째 DataGridView가 채워지지 않습니다. 두 번째 datagridview가 1 초 내에 채워질 것으로 예상하고 첫 번째 datagridview가 30 초 후에 채울 것으로 예상합니다.
OleDBDataAdapter 및 SqlDataAdapter를 모두 사용하여 샘플 코드에서이 문제점을 중복 시켰습니다. 장기 실행 쿼리를 간단한 Thread.Sleep (30000)으로 바꾸면 두 번째 DataGridview가 바로 채워집니다. 이것은 필자가 디자인 패턴에 문제가 없다고 믿게한다. 동시에 .Fill 호출을 발행하는 것과 관련이있다.
Private Async Sub UltraButton1_Click(sender As Object, e As EventArgs) Handles UltraButton1.Click
Dim Args As New GetDataArguments
Args.ConnectionString = "some connection string"
Args.Query = "SELECT LongRunningQuery from Table"
Dim DT As DataTable = Await Task.Run(Function() FillDataTable(Args))
If DataGridView1.DataSource Is Nothing Then
DataGridView1.DataSource = DT
Else
CType(DataGridView1.DataSource, DataTable).Merge(DT)
End If
End Sub
Function FillDataTable(Args As GetDataArguments) As DataTable
Dim DS As New DataTable
Using Connection As New OleDbConnection(Args.ConnectionString)
Using DBCommand As New OleDbCommand(Args.Query, Connection)
Using DataAdapter As New OleDbDataAdapter(DBCommand)
DataAdapter.Fill(DS)
End Using
End Using
End Using
Return DS
End Function
Private Async Sub UltraButton2_Click(sender As Object, e As EventArgs) Handles UltraButton2.Click
Dim DS As DataTable = Await Task.Run(Function() LoadSecondDGV("1234"))
DataGridView2.DataSource = DS
End Sub
Function LoadSecondDGV(pnum As String) As DataTable
Dim DX As New DataTable
Using xConn As New OleDbConnection("some connection string")
Using DataAdapter As New OleDbDataAdapter("Select name from products where PNUM = """ & pnum & """", xConn)
DataAdapter.Fill(DX)
End Using
End Using
Return DX
End Function
실제로 Access 데이터베이스를 사용하고 있지만 정확히 동일한 동작으로 SQL Server에 대한 테스트를 시뮬레이션했습니다. 두 경우 모두 관련없는 테이블을 완전히 질의하여 자신을 차단하지 못하게했습니다. 나는 SQL 인젝션 경고에 감사한다. 이것은 단지 빠르고 불결한 PoC winform 코드 일 뿐이다. 다른 생각? 연결 문자열 등의 특성을 고려하여 여기에 실행 준비 코드가 없다는 것을 알았지 만 문제를 재현 할 수 있는지 여부는 매우 궁금합니다. – rSquared
실제로 각 스레드에서 서로 관련이없는 두 개의 Access 데이터베이스를 완전히 쿼리 할 경우 문제가 발생합니다. 즉, DataAdapter 객체의 본래의 것이 스레드간에 공유되는 것을 의미합니까? – rSquared
@rSquared 나는 당신이 이것을하기 위해'async'를 사용하고 있다는 것을 깨달았습니다. 'async'가 다중 쓰레드를 사용하지 않는 ** 것을 이해하는 것이 중요합니다.그것은 같은 thread_에서 순서가 어긋나도록 허용합니다. 그것은 병렬성의 _appearance_을 제공하고, 매우 자주 (** 많은 **) CPU 또는 단일 스레드의보다 효율적인 사용을하지만, 실제로 병렬 아니에요. 데이터베이스 호출과 같이 차단하는 항목이 있으면 계속해서 하나의 호출 완료를보고 다른 호출은 계속 볼 것입니다. –