2015-06-15 9 views
8
void itemCommand_Click(Office.CommandBarButton Ctrl, ref bool CancelDefault) 
{ 
    var thread = new Thread(() => 
    { 
    if (LoginCheck()) 
    { 
     ItemWindow itw = new ItemWindow(); 
     //Dispatcher.CurrentDispatcher.Invoke((System.Action)(() => 
     //{ 
       itw.Show(); 
       itw.Closed += (sender2, e2) => { itw.Dispatcher.InvokeShutdown(); }; 
     //})); 

     Dispatcher.Run(); 
    } 
    }); 

    thread.SetApartmentState(ApartmentState.STA); 
    thread.Start(); 

} 

मुझे त्रुटि संदेश मिल रहा है "कॉलिंग थ्रेड इस ऑब्जेक्ट तक नहीं पहुंच सकता क्योंकि एक अलग धागा इसका मालिक है।" लाइन पर "itw.show();" जब इस समारोह को दो बार बुलाया जाता है। यह पहली कॉल के लिए ठीक काम करता है, और खिड़की बंद होने के बाद और फिर से खोलने की कोशिश करने के बाद, यह विफल हो जाता है। जैसा कि मैंने "Invoke" विधि पर टिप्पणी की है, यह डिस्पैचर के साथ भी काम नहीं करता है। समाधान खोजने के लिए कृपया मेरी मदद करें। धन्यवाद।नई थ्रेड त्रुटि पर WPF नई विंडो निर्माण

----------------- संपादित

कारण है कि मैं एक नया धागा बना रहा हूं क्योंकि यह एक एक्सेल ऐड है। मैं मुख्य धागे से खिड़कियां नहीं बना सकता जो कि एक्सेल है जो खिड़कियों के साथ टकराता है अगर मैं उन्हें मुख्य धागे से बना देता हूं।
जो चीज़ मुझे समझ में नहीं आती है वह यह है कि नए धागे से नया उदाहरण (आइटमविंडो) पुराने धागे से टकराता है।

+2

आप इस विंडो को दिखाने के लिए एक नया धागा क्यों बनाना चाहते हैं? यह आम तौर पर एक अच्छा विचार नहीं है। और, दूसरी बात, मैंने यह कोशिश की है और यह ठीक काम करता है (सिवाय इसके कि मुझे नहीं पता कि 'लॉग इन चेक' क्या करता है)। अपवाद कहां होता है? –

+2

सभी यूआई संबंधित कोड मुख्य धागे में चलाना चाहिए। आप यहां क्या हासिल करने की कोशिश कर रहे हैं? – almulo

+0

आम तौर पर यह त्रुटि आपको उस थ्रेड से आपके पहले फॉर्म पर किसी संपत्ति तक पहुंचने का प्रयास करने का संदर्भ देती है। हमें वास्तव में देखना होगा कि इस मुद्दे के कारण दूसरे फॉर्म पर क्या होता है। – DoomVroom

उत्तर

0

मैंने एक नए एप्लिकेशन में एक साधारण परीक्षण विधि बनाई जिसे कॉल किया जाता है जब मैं अपने मुख्य रूप पर (केवल) बटन पर क्लिक करता हूं। विधि इस प्रकार है:

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    Thread thread = new Thread(() => 
    { 
     Window1 window = new Window1(); 
     window.Closed += (s, a) => window.Dispatcher.InvokeShutdown(); 
     window.Show(); 
     System.Windows.Threading.Dispatcher.Run(); 
    }); 

    thread.SetApartmentState(ApartmentState.STA); 
    thread.Start(); 
} 

Window1 एक विंडो वर्ग मुझे लगता है कि लेकिन एक भी TextBlock इस पर कुछ भी नहीं है बनाया है। मैं जितनी बार चाहूं उतनी बार उस बटन पर क्लिक कर सकता हूं, और यह बिना किसी समस्या के नई विंडो खोलना जारी रखता है (भले ही मैं पहले पिछले को बंद करता हूं या नहीं)।

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

एक कदम पीछे लेना, यह क्यों महत्वपूर्ण है कि नई खिड़की अपने धागे पर हो? जब तक नई खिड़की धागे का एकाधिकार करने जा रही है, तो यह संभवतः मुख्य धागे पर ठीक से चलती है। यदि आप कुछ लंबे अवरुद्ध ऑपरेशन चला रहे हैं, तो शायद उस ऑपरेशन को पूरी खिड़की के बजाए धागे में ले जाया जाना चाहिए। मुझे नहीं पता कि आप वास्तव में क्या कर रहे हैं, लेकिन यह सोचने के लिए कुछ है।


संपादित करें: यह महसूस करते हुए कि आप एक विशिष्ट WPF आवेदन में न चल रहा हो (लगता है कि आप किसी Office प्लगइन में हो सकता है), मैं शुरू करने के लिए खिड़कियां पूरी तरह से अपने स्वयं के धागे पर स्वसंपूर्ण अपने परीक्षण अपडेट किया गया। हालांकि, मैं अभी भी बिना किसी समस्या के दो पंक्तियों को लॉन्च करने में सक्षम हूं।

मेरा नया परीक्षण यहां है। यह विधि और परीक्षण वर्ग Window1 मेरे आवेदन की पूरी तरह से हैं।

[STAThread] 
public static int Main(string[] args) 
{ 
    ThreadStart threadFunc =() => 
    { 
     Window1 window = new Window1(); 
     window.Closed += (s, a) => window.Dispatcher.InvokeShutdown(); 
     window.Show(); 
     System.Windows.Threading.Dispatcher.Run(); 
    }; 

    Thread thread = new Thread(threadFunc); 
    thread.SetApartmentState(ApartmentState.STA); 
    thread.Start(); 
    thread.Join(); 

    thread = new Thread(threadFunc); 
    thread.SetApartmentState(ApartmentState.STA); 
    thread.Start(); 
    thread.Join(); 

    return 0; 
} 

तो, तुम क्या करने कोशिश कर रहे हैं के साथ स्वाभाविक कुछ भी गलत नहीं प्रतीत होता है, और न ही मैं अपने कोड में किसी भी स्पष्ट मुद्दा दिख रहा है। मुझे संदेह है कि कुछ कस्टम क्रॉस-थ्रेड संचार आपके कस्टम विंडो में कहीं भी हो रहा है जबकि यह दिखाया जा रहा है। (या तो, या आप Office plugins के लिए विशिष्ट समस्या में चल रहे हैं।)

+0

मुझे लगता है कि यह एक्सेल एडिन के साथ कुछ करना है। जिस चीज को मैं समझ नहीं पा रहा हूं वह यह है कि नए धागे से नया उदाहरण (आइटमविंडो) पुराने धागे से टकराता है। – icewall

+0

क्या आपने अपवाद के कॉलस्टैक को देखा है? शायद यह अमान्य कॉल करने के बारे में कुछ संकेत बताएगा। साथ ही, आप दृश्य स्टूडियो में कॉल स्टैक विंडो में पूर्ण कॉलस्टैक (बाहरी असेंबली से विधियों सहित) देखने के लिए "जस्ट माई कोड" डीबगर विकल्प को बंद कर सकते हैं। – Xavier

0

के बाद आप ईवेंट हैंडलर को आइटमविंडो से कनेक्ट करने का प्रयास कर रहे हैं, यह पहले से दिखाई दे रहा है।

ItemWindow itw = new ItemWindow(); 
itw.Show(); 
itw.Closed += (sender2, e2) => { itw.Dispatcher.InvokeShutdown(); }; 

ItemWindow itw = new ItemWindow(); 
itw.Closed += (sender2, e2) => { itw.Dispatcher.InvokeShutdown(); }; 
itw.Show(); 
-1

लिए एक संभावित कारण निर्भरता गुण हैं:

आप से आदेश स्विच करना होगा। जब थ्रेडिंग की बात आती है तो निर्भरता गुण थोड़ा चुनिंदा होते हैं।

भले ही आप अपने स्वयं के DepProps को परिभाषित नहीं करते हैं, फिर भी आपकी खिड़की में कुछ होगा और उनसे छुटकारा पाने का कोई तरीका नहीं है।

DepProps का एक महत्वपूर्ण नकारात्मक पक्ष है: वे थ्रेड बाध्य हैं और किसी अन्य धागे से नहीं पहुंचा जा सकता है। कौन सा धागा सभी अधिकारों को थ्रेड द्वारा परिभाषित किया गया है जो डेपप्रॉप को प्रारंभ करता है, आपके मामले में new ItemWindow() पर पहला कॉल। उसके बाद पहले अपना थ्रेड सेट करें और आपको अपने डेपप्रॉप तक पहुंचने के लिए उस थ्रेड की आवश्यकता है।

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

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