2011-04-24 17 views
5

यह एक तकनीक है जिसे मैंने नेटवर्क डेटा प्राप्त करने के लिए वर्षों से उपयोग किया है और इसे अपने जीयूआई (संवाद, फॉर्म इत्यादि) में उपयोग किया है।थ्रेड से रीयलटाइम गुई अपडेट्स को तेज करना

public delegate void mydelegate(Byte[] message); 

    public ReceiveEngineCS(String LocalIpIn, String ReceiveFromIp, mydelegate d) 
    { 
     this.m_LocalIpIn = LocalIpIn; 
     this.m_ReceiveFromIp = ReceiveFromIp; 
     m_MainCallback = d; 
     SetupReceive(); 
     m_Running = true; 
     //Create the Track receive thread and pass the parent (this) 
     m_RtdirReceiveThread = new Thread(new ParameterizedThreadStart(MessageRecieveThread)); 
     m_RtdirReceiveThread.Start(this); 
    } 

    private void MessageRecieveThread(System.Object obj) 
    { 
     ReceiveEngineCS parent = (ReceiveEngineCS)obj; 

     while(parent.m_Running) 
     { 
       Byte[] receiveBytes = new Byte[1500]; 
       try 
       { 
        receiveBytes = parent.m_ClientReceiver.Receive(ref parent.ipEndPoint); 
        parent.ThreadOutput(receiveBytes); 
       } 
       catch (Exception e) 
       { 
        parent.StatusUpdate(e.ToString()); 
       }       
     }   
    } 

    public void ThreadOutput(Byte[] message) 
    { 
     m_MainCallback(message);   
    } 

public partial class SystemMain : Form 
{ 
    //Local Class Variables 
    Network.ReceiveEngineCS SystemMessageReceiver; 
    private void Form1_Load(object sender, EventArgs e) 
    { 
     //Load up the message receiver 
     SystemMessageReceiver = new Network.ReceiveEngineCS(localAddy, fromAddy, new mydelegate(LocalDelegate)); 
    } 

    public void LocalDelegate(Byte[] message) 
    { 
     if (Form.ListView.InvokeRequired) 
     { 
      //External call: invoke delegate 
      Form.ListView.Invoke(new mydelegate(this.LocalDelegate), message); 
     } 
     else 
     { 
      //Get the Packet Header 
      Formats.PacketHeaderObject ph = new Formats.PacketHeaderObject(message); 
      //Update or Add item to Specific ListView 
      ... update views 
     } 
    } 
} 

रिसीवर कहीं भी 10 और 100 रीयल-टाइम संदेशों के बीच कहीं और अक्सर लेता है।

मैं हाल ही में नेट 4.0 और सी # में शोध कर रहा हूं और इस डेटा प्रोसेसिंग , जैसे वर्कर थ्रेड, और प्रतिनिधि और आमंत्रण का उपयोग करने के अन्य तरीकों को करने के कई अन्य समान तरीकों को देखा है।

मेरा प्रश्न ... क्या इस डेटा को प्राप्त करने/जीयूआई अपडेट करने के लिए नए .NET पुस्तकालयों (3.5, 4.0 आदि) में एक और अधिक प्रभावी तरीका है?

मुझे लगता है कि यह विधि सी # के साथ-साथ काम नहीं कर रही है।

किसी भी मदद की सराहना की जाएगी।

+1

किसी उपयोगकर्ता पर प्रति सेकेंड एक सौ नोटिफिकेशन फेंकना ज्यादा समझ में नहीं आता है। यह एक धुंध की तरह दिखेगा। अपने UI को पहले प्रयोग करने योग्य बनाएं, आपकी समस्या भी हल करें। Winforms में कोई बदलाव नहीं है। –

+0

अच्छा विचार हंस। यदि मैं थ्रेड में आने वाले डेटा के बारे में मेटा डेटा बनाता हूं और केवल हर दूसरे को गुई अपडेट करता हूं या तो यह डेटा के बारे में एक सभ्य उपयोगकर्ता प्रतिक्रिया देगा, जबकि गुई को अपडेट के साथ उलझने की इजाजत नहीं दी जाएगी। आम तौर पर ऑपरेटर डेटा दर के बारे में एक गाइड के रूप में अद्यतन डेटा आइटम की किसी न किसी गिनती का उपयोग करता है। तो एक नज़र में दस सेकेंड 50 सेकेंड की गिनती इत्यादि। लेकिन मैं मेटा अपडेट के रूप में इसे समेकित कर सकता हूं और सूचीदृश्य में जोड़ सकता हूं। – Sleff

उत्तर

4

एक जीयूआई में अपडेट पोस्ट करने का सबसे अच्छा तरीका है कि कार्यकर्ता थ्रेड को अद्यतन में शामिल डेटा को पैकेज करना और उसे कतार में रखना है। यूआई थ्रेड तब कतार को समय-समय पर मतदान करेगा। यूआई को अपडेट करने के लिए वर्कर थ्रेड Control.Invoke का उपयोग करने के लिए रास्ता मेरी राय में अधिक उपयोग किया जाता है। इसके विपरीत, अपडेट के लिए यूआई थ्रेड पोल होने के कई फायदे हैं।

  • यह यूआई और कार्यकर्ता धागे के बीच तंग युग्मन तोड़ता है जो Control.Invoke लगाता है।
  • यह UI थ्रेड पर UI थ्रेड को अपडेट करने की ज़िम्मेदारी रखता है जहां इसे वैसे भी होना चाहिए।
  • यूआई थ्रेड निर्देशित करता है कि अपडेट कब और कितनी बार होनी चाहिए।
  • यूआई संदेश पंप को ओवररन करने का कोई खतरा नहीं है क्योंकि वर्कर थ्रेड द्वारा शुरू की गई मार्शलिंग तकनीकों के मामले में मामला होगा।
  • कार्यकर्ता धागे को अपने अगले चरणों के साथ आगे बढ़ने से पहले अद्यतन किया गया था (यानी आप यूआई और कार्यकर्ता धागे दोनों पर अधिक थ्रूपुट प्राप्त करते हैं)।

आपने उल्लेख नहीं किया कि कैसे ThreadOutput लागू किया गया था, लेकिन आप उपरोक्त वर्णित दृष्टिकोण पर विचार कर सकते हैं यदि यह पहले से ही नहीं किया गया है। अनुभव ने मुझे सिखाया है कि यह आमतौर पर सबसे अच्छा तरीका है। यूआई थ्रेड को अपने अपडेट चक्र को थ्रॉटल करने देना एक बड़ा फायदा है।

+0

एक साझा संसाधन से मतदान डेटा के साथ मेरी समस्या हमेशा एक समय रही है।साझा कतार को लॉक करने और अनलॉक करने से बहुत अधिक ओवरहेड होता है (नहीं कि मुझे निश्चित रूप से उस समस्या का सामना नहीं करना पड़ रहा है)। मैंने कार्यकर्ता धागे में देखा है और देखा है कि धागे के लिए अद्यतन वापस भेजने के लिए एक तंत्र है। मुझे यह सुनिश्चित नहीं था कि क्या यूआई के स्वामित्व वाली कतार को अपडेट करने के लिए कार्यकर्ता थ्रेड के लिए किसी आविष्कार का उपयोग करना था या नहीं? – Sleff

+0

कतार का लॉकिंग 'Control.Invoke' की तुलना में कुछ भी नहीं है जो एक बेहद महंगी ऑपरेशन है। इसके अलावा, आप हमेशा 'ConcurrentQueue' का उपयोग कर सकते हैं जो लॉक-फ्री तंत्र का उपयोग करता है। कार्यकर्ता थ्रेड को कतार में कुछ पोस्ट करने के लिए 'Invoke' का उपयोग नहीं करना पड़ता है। यह पहली जगह में "यूआई स्वामित्व वाली कतार" कहने के लिए थोड़ा भ्रामक हो सकता है। –

+0

इससे @Brian मदद करता है। मैं आक्रमण की कीमत से अनिश्चित था। मैंने हमेशा इसे सरल फ़ाइलों या कम दर वाले एक्सएमएल डेटा से गुई को अद्यतन करने के सरल उदाहरणों में उपयोग किया था। मैं ConcurrentQueue की जांच करूंगा और @ हंस के सुझाव के रूप में अपडेट करने की आवश्यकता को कम करने में भी देखूंगा। – Sleff

1

हर बार नए धागे कताई के बजाय Thread Pooling पर एक नज़र डालें।

+0

धन्यवाद ज़ंबोनी लेकिन मैं वास्तव में केवल एक थ्रेड का उपयोग कर संदेश के लिए पूरे जीवनकाल प्राप्त करता हूं। संदेश उन घटनाओं के निरंतर अद्यतन होते हैं जिन्हें मुझे हर समय प्राप्त करने की आवश्यकता होती है। – Sleff

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