내 문제는 실제 프로젝트 문제를 기반으로하지만 난 System.Threading.Tasks
라이브러리를 사용하거나 스레드와 관련된 심각한 프로그래밍을 수행 한 적이 없어 내 질문에 특정 라이브러리에 대한 지식이 부족할 수 있습니다 프로그래밍 측면에서 비동기가 실제로 의미하는 바를 오해하고 있습니다.정말 비동기 두 SQL 쿼리를 만드는 방법
내 실제 사례가 있습니다. 사용자에 대한 데이터를 가져와야합니다. 현재 시나리오에서는 재무 데이터이므로 모든 사용자에게 Accounts
, 모두 Deposits
및 모두 Consignations
이 필요하다고 가정 해 보겠습니다. 내 경우에 이것은 각 속성에 대한 백만 건의 레코드를 쿼리하는 것을 의미하며 각 쿼리는 상대적으로 느려지므로 을 가져 오려면 Deposits
을 가져 오는 것보다 몇 배 느립니다. 그래서 나는 내가 사용하는거야 세 은행 제품에 대한 세 가지 클래스를 정의하고 난 특정 사용자의 모든 은행 제품에 대한 데이터를 가져 오기 할 때이 같은 수행
List<Account> accounts = GetAccountsForClient(int clientId);
List<Deposit> deposits = GetDepositsForClient(int clientId);
List<Consignation> consignations = GetConsignationsForClient(int clientId);
그래서 문제가 시작을 여기에 모든 세 가지 목록을 동시에 가져와야합니다. 왜냐하면 모든 사용자 데이터를 표시하는보기로 전달하기 때문입니다. 그래서 세 제품 모두에 대한 데이터를 수집하기위한 총 시간 (내가 제대로 여기 용어를 사용하고있는 경우)가 바로 지금 실행이 동기하지만입니다 :
Total_Time = Time_To_Get_Accounts + Time_To_Get_Deposits + Time_To_Get_Consignations
이 좋지 않아 각 쿼리 때문에 상대적으로 느리기 때문에 총 시간이 꽤 길지만 accounts
쿼리는 다른 두 쿼리보다 훨씬 많은 시간이 걸리므로 오늘 내 머리 속에 들어간 아이디어는 "이 쿼리를 동시에 실행할 수 있다면 어떨까요?"입니다. 어쩌면 내 주제에 대한 나의 가장 큰 오해가 내게이 아이디어에 가장 가까운 것은 비동기 적이기 때문에 Total_Time
은 가장 느린 쿼리 시간이 아니지만 세 쿼리의 합보다 훨씬 빠르다.
내 코드가 복잡하기 때문에 간단한 사용 사례를 만들었고, 내가 잘하려고 노력한 것을 반영했다.
public static async Task<int> GetAccounts()
{
int total1 = 0;
using (SqlConnection connection = new SqlConnection(connString))
{
string query1 = "SELECT COUNT(*) FROM [MyDb].[dbo].[Accounts]";
SqlCommand command = new SqlCommand(query1, connection);
connection.Open();
for (int i = 0; i < 19000000; i++)
{
string s = i.ToString();
}
total1 = (int) await command.ExecuteScalarAsync();
Console.WriteLine(total1.ToString());
}
return total1;
}
와 두 번째 방법 : 나는 두 가지 방법이이 같은 전화
public static async Task<int> GetDeposits()
{
int total2 = 0;
using (SqlConnection connection = new SqlConnection(connString))
{
string query2 = "SELECT COUNT(*) FROM [MyDb].[dbo].[Deposits]";
SqlCommand command = new SqlCommand(query2, connection);
connection.Open();
total2 = (int) await command.ExecuteScalarAsync();
Console.WriteLine(total2.ToString());
}
return total2;
}
:
static void Main(string[] args)
{
Console.WriteLine(GetAccounts().Result.ToString());
Console.WriteLine(GetDeposits().Result.ToString());
}
당신은 내가 처음 GetAccounts()
를 호출하고 나는 실행을 느리게 볼 수 있듯이 그래서 나는 다음 번 방법으로 계속할 수있는 기회를 준다. 그러나 나는 일정 시간 동안 어떤 결과도 얻지 못하고 있으며, 동시에 콘솔에 모두 인쇄됩니다.
그래서 문제 - 다음 방법으로 이동하기 위해 첫 번째 방법을 마칠 때까지 기다리지 않으려면 어떻게해야합니까? 일반적으로 코드 구조는 그리 중요하지 않습니다. 두 가지 쿼리가 동시에 실행될 수있는 방법이 있다면 알아 내고 싶습니다. 여기 샘플은 내가 원하는 결과를 얻을 수있는 지점까지 확장 될 수있는 나의 연구 결과입니다.
P.S 나는 그것을 사용하고있는 방법으로 시작했기 때문에 ExecuteScalarAsync();
을 사용하고 있습니다. 실제로 나는 Scalar
과 Reader
을 사용할 것입니다.
. 저의 원래 생각은 다른 순간에 결과를 얻는 것이 었습니다. 귀하의 설명에서 나는이 총 시간이 가장 느린 시간과 같을 것이라고 생각하지만 두 번째 메소드'for (int i = 0; i <19000000; i ++)를 추가했을 때 { string s = i.ToString(); }'시간이 두 배로 늘어났습니다. 이상합니다. 그것이 동시 적이었고이 경우 쿼리에 밀리 초가 걸리므로 메서드 중 하나만 느려지는 것과 같은 시간을 기다리고있었습니다. – Leron
내가 스스로를 분명하게하는지 확실하지 않습니다. 내 생각에'GetAccounts()'가 3 초가 걸리고'GetDeposits()'가 초보다 작 으면 결과를 얻는데 3 초가 걸릴 것이라고 생각한다. 하지만 GetDeposits()를 3 초 동안 실행하지 않고 3 초 동안 실행하도록하면, 가장 느린 시간이고 작업이 동시에 실행되므로 6 초 후에 결과를 얻습니다. 이 접근법을 그대로 사용하면 일어나는 일이 거의 발생합니다. 내가 놓친 게 있니? – Leron
@Leron 비동기는 병렬과 동일하지 않습니다. 메소드에는 비동기 파트와 동기 파트 (I/O 및 CPU)가 있습니다. 비동기 파트를 내 대답과 마찬가지로 동시에 실행할 수 있습니다. 동기 부분을 병렬로 실행하려면 'Task.Run'과 함께 2 개의 쓰레드를 사용해야합니다. 너가 원하는게 그거야? – i3arnon