2010-01-21 12 views
8

सी #/.NET 3.5 का उपयोग करना।SqlDataAdapter.Fill - असीमित दृष्टिकोण

वर्तमान में मैं 2 डेटाटेबल्स को दूसरे के बाद SqlDataAdapter.Fill() का उपयोग कर रहा हूं।

मैं इन दोनों डेटाटेबल्स को समानांतर में एक साथ जोड़ना चाहता हूं, साथ ही साथ प्रत्येक एक को अतुल्यकालिक रूप से कर सकता हूं। हालांकि, फिल() विधि का कोई असीमित संस्करण नहीं है - यानी BeginFill() बहुत अच्छा होगा!

  1. SqlCommand1.BeginExecuteReader // 1 क्वेरी, DataTable1 के लिए
  2. SqlCommand2.BeginExecuteReader // 2 क्वेरी, DataTable2
  3. SqlCommand1.EndExecuteReader के लिए:

    एक दृष्टिकोण मैं कोशिश की है (छद्म) है

  4. SqlCommand2.EndExecuteReader
  5. DataTable1.Load (DataReader1)
  6. DataTable2.Load (DataReader2)

हालांकि, DataTable.Load() एक लंबा समय लगता:
यह 3 सेकंड लेता है चरण 1 करने के लिए कदम 4
चरण 5 तो 22 सेकंड लेता है।
चरण 6 में 17 सेकंड लगते हैं।
तो, चरण 5 और 6 के लिए 39 सेकंड संयुक्त।

अंत परिणाम यह है कि यह मुझे 2 SqlDataAdapter.Fills करने पर कोई लाभ नहीं देता है, एक के बाद एक। मैं नेट परिणाम चाहता हूं कि पूरी प्रक्रिया केवल सबसे लंबी क्वेरी (या जितनी संभव हो सके उतनी करीब) के रूप में लेती है।

डेटाटेबल भरने के लिए वास्तव में एक असीमित दृष्टिकोण के साथ समाप्त होने के लिए अनुशंसित तरीकों की तलाश करना।

या क्या मैं इसे स्वयं प्रबंधित करता हूं और 2 अलग-अलग धागे रोल करता हूं, प्रत्येक डेटाटेबल भरता है?

उत्तर

5

मैं सुझाव दूंगा कि प्रत्येक के लिए एक अलग कार्यकर्ता धागा होगा। आप ThreadPool.QueueUserWorkItem का उपयोग कर सकते हैं।

List<AutoResetEvent> events = new List<AutoResetEvent>(); 

AutoResetEvent loadTable1 = new AutoResetEvent(false); 
events.Add(loadTable1); 
ThreadPool.QueueUserWorkItem(delegate 
{ 
    SqlCommand1.BeginExecuteReader; 
    SqlCommand1.EndExecuteReader; 
    DataTable1.Load(DataReader1); 
    loadTable1.Set(); 
}); 

AutoResetEvent loadTable2 = new AutoResetEvent(false); 
events.Add(loadTable2); 
ThreadPool.QueueUserWorkItem(delegate 
{ 
    SqlCommand2.BeginExecuteReader; 
    SqlCommand2.EndExecuteReader; 
    DataTable2.Load(DataReader2); 
    loadTable2.Set(); 
}); 

// wait until both tables have loaded. 
WaitHandle.WaitAll(events.ToArray()); 
+0

तो एक बार मैं हर एक अप पंक्तिबद्ध है, मैं दोनों जब तक कैसे इंतजार कर सकते हैं पूरा कर लिया है? मुझे जारी रखने से पहले दोनों टेबलों की आवश्यकता होती है और उन्हें – AdaTheDev

+0

संसाधित करता है, यदि मैंने मदद की है तो मैंने अपने उत्तर में प्रतीक्षा अवधारणा को जोड़ा है। –

+0

@AdaTheDev, आप AutoResetEvents का उपयोग करेंगे जो काम पूरा होने के बाद ट्रिगर करेगा (प्रत्येक अलग थ्रेड के अंदर)। @Neils उत्तर देखें क्योंकि उसने पहले ही एक उदाहरण प्रदान किया है। – James

1

इसका कारण यह है DataTable वस्तुओं का एक बहुत (पंक्तियाँ, मान) बनाने के लिए है। आपके पास एडाप्टर और एक अलग थ्रेड में किए गए डेटाटेबल की आबादी का निष्पादन होना चाहिए, और जारी रखने से पहले प्रत्येक ऑपरेशन को समाप्त करने के लिए प्रतीक्षा करना सिंक्रनाइज़ करना चाहिए।

निम्नलिखित कोड नोटपैड में लिखा गया था और शायद यहां तक ​​कि संकलन नहीं है, लेकिन उम्मीद है कि आपको अंदाजा हो ...

// Setup state as a parameter object containing a table and adapter to use to populate that table here 

void DoWork() 
{ 
    List<AutoResetEvent> signals = GetNumberOfWaitHandles(2); 

    var params1 = new DataWorkerParameters 
     { 
      Command = GetCommand1(); 
      Table = new DataTable(); 
     } 

    var params2 = new DataWorkerParameters 
     { 
      Command = GetCommand2(); 
      Table = new DataTable(); 
     } 

    ThreadPool.QueueUserWorkItem(state => 
     { 
      var input = (DataWorkerParameters)state; 
      PopulateTable(input); 
      input.AutoResetEvent.Set(); // You can use AutoResetEvent.WaitAll() in the caller to wait for all threads to complete 
     }, 
     params1 
    ); 

    ThreadPool.QueueUserWorkItem(state => 
     { 
      var input = (DataWorkerParameters)state; 
      PopulateTable(input); 
      input.AutoResetEvent.Set(); // You can use AutoResetEvent.WaitAll() in the caller to wait for all threads to complete 
     }, 
     params2 
    ); 

    WaitHandle.WaitAll(signals.ToArray()); 
} 


void PopulateTable(DataWorkerParameters parameters) 
{ 
    input.Command.ExecuteReader(); 
    input.Table.Load(input.Command); 
} 
+0

धन्यवाद (दोनों)। मैं एक एसटीए थ्रेड पर चल रहा हूं, जिसका मतलब है कि मैं WaitHandle.WaitAll का उपयोग नहीं कर सकता ("एसटीए थ्रेड पर एकाधिक हैंडल के लिए प्रतीक्षा करें समर्थित नहीं है")। क्या कोई विकल्प है? – AdaTheDev

+0

आप एक 'एक्शन' कॉलबैक प्रदान कर सकते हैं, जो कोड के अगले बिट को केवल पर्याप्त समय कहा जाता है? बहुत अच्छा नहीं है, लेकिन काम करना चाहिए। सुझाव और सहायता के लिए –

+0

चीयर्स। मैं जो चाहता था उसे करने के लिए पर्याप्त काम कर रहा था (फिर एक दूसरे के साथ दबाने के समानांतर में प्रश्नों को चलाने का कोई वास्तविक लाभ नहीं था)। जवाब के लिए +1 क्योंकि यह मदद की थी। – AdaTheDev

संबंधित मुद्दे