2011-08-28 15 views
7

मेरे पास एक सर्वर क्लास है जो मूल रूप से क्लाइंट से कनेक्शन के लिए प्रतीक्षा करती है। उस क्लास के अंदर मैं क्लाइंट से बाइट प्राप्त करने में सक्षम होने के लिए नेटवर्कस्ट्रीम ऑब्जेक्ट बनाता हूं। चूंकि NetworkStream.Read() विधि एसिंक्रोनस नहीं है (जिसका अर्थ यह है कि जब तक यह संदेश बॉक्स विधि के समान निष्पादन कोड को आगे बढ़ाने के लिए क्लाइंट से बाइट्स को पढ़ता है तब तक इंतजार करेगा), मुझे बाइट्स को एक अलग थ्रेड में पढ़ना होगा ताकि यदि प्रोग्राम डेटा के लिए पढ़ने का इंतजार कर रहा है तो प्रोग्राम का उपयोग कर उपयोगकर्ता अभी भी प्रोग्राम के साथ बातचीत कर सकता है।एक अलग थ्रेड से एक्सेस ऑब्जेक्ट

वैसे भी बहुत सारी ऑब्जेक्ट्स उस धागे के स्वामित्व में हैं। एक उदाहरण यह है कि मेरे पास उस वर्ग में लॉग नामक एक सूची है। मैं सर्वर की स्थिति जानने के लिए उस सूची का उपयोग करता हूं। शायद यह एक कनेक्शन के लिए सुन रहा है या शायद इसकी स्थिति "जुड़ा हुआ" या "डिस्कनेक्ट" है।

तो अगर मैं कुछ ऐसा कार्य करें:

public delegate void onUpdateHandler(string newStatus); 
    public event onUpdateHandler onUpdate = delegate { }; 

मैं तो आग:

Server myServer = new Server("192.168.0.120","1300"...\\ I pass the appropite parameters in order to instantiate it 

//... 
.. then I am able to latter look at the log as 
string foo = myServer.Log[0] for example. 

क्योंकि मुझे पता है कि जब लॉग अद्यतन किया जाता है चाहता हूँ, सर्वर वर्ग पर मैं के रूप में एक ईवेंट बनाया है के रूप में सर्वर वर्ग पर घटनाओं:

onUpdate("waitingForConnection"); 

और मैं विधि के साथ उन घटनाओं प्राप्त करते हैं:

enter image description here

लेकिन अगर मैं NEWSTATUS साथ कुछ करने की कोशिश मैं त्रुटि बताते हुए मिलती है:

System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it. 

तो कैसे मैं एक घटना के साथ एक वस्तु पारित कर सकते हैं?


संपादित

तो मैं भी ध्यान दें कि अगर मैं कार्य करें:

enter image description here

मैं भी कोई त्रुटि मिलती है!

लेकिन जब मैं एक ही बात एक बटन से फोन कर रहा है कि के रूप में कार्य करें:

// SERVER IS RUNNING BEFORE CALLING THIS METHOD 
    private void button3_Click(object sender, RoutedEventArgs e) 
    { 

     listView1.Items.Add("my own string"); 

    } 

मैं एक त्रुटि नहीं मिलता है!

यह क्यों है कि मुझे घटना के साथ कोई त्रुटि मिलती है और मुझे नियमित बटन के साथ कॉल करते समय कोई त्रुटि नहीं होती है।

Application.Current.Dispatcher.Invoke((Action)(() => 
{ 
    listView1.Items.Add(newStatus); 
})); 

यह भी देखें:

उत्तर

12
समस्या

कि धागा ListView जो एक DependencyObject जो धागा संबंध है है का उपयोग करने की कोशिश करता है, Dispatcher का उपयोग यूआई-धागे पर इस तरह के तरीकों पर अमल करने, जैसे है अतिरिक्त जानकारी के लिए threading model reference

+0

जब मुझे लगता है कि अंदर जगह मेरी विधि मुझे एक त्रुटि बताती है: 'सिस्टम। डिलीगेट' टाइप करने के लिए लैम्ब्डा अभिव्यक्ति को परिवर्तित नहीं किया जा सकता क्योंकि यह एक प्रतिनिधि प्रकार –

+0

@ टोनोनाम नहीं है: ओह हाँ, आपको इसे कास्ट करने या स्पष्ट रूप से एक क्रिया बनाने की आवश्यकता है। –

+0

@ टोनो, लैम्ब्डा को कुछ प्रतिनिधि प्रकारों में डाला जाना है, मेरा संपादन देखें। – svick

1

समस्या यह नहीं है कि आप विधि में भेजे गए मान के साथ कुछ करने का प्रयास करें, समस्या यह है कि आप इसके साथ क्या करने का प्रयास कर रहे हैं।

इवेंट हैंडलर अभी भी आपके पृष्ठभूमि धागे में चल रहा है, और वहां से आप किसी भी UI नियंत्रण का उपयोग नहीं कर सकते क्योंकि वे मुख्य धागे से संबंधित हैं।

से निपटने का हमेशा की तरह की जाँच करने के CheckAccess विधि का उपयोग करने अगर आप ट्रेड्स स्विच करने की आवश्यकता है, और मुख्य थ्रेड पर काम बंद हाथ करने के लिए Invoke विधि:

void server_onUpdate(string newStatus) { 
    if (!listView1.Dispatcher.CheckAccess()) { 
    listView1.Dispatcher.Invoke(server_onUpdate, newStatus) 
    } else { 
    listView1.Items.Add(newStatus); 
    } 
} 
+0

के लिए धन्यवाद टैग इस WinForms नहीं है ... –

+0

@ H.B के अनुसार .: मैं पहले से ही है कि ठीक कर दिया। – Guffa

+0

@Guffa अच्छा स्पष्टीकरण धन्यवाद –

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