2010-03-04 11 views
36

मेरे डब्ल्यूपीएफ एप्लिकेशन में मैं कुछ एसिंक संचार (सर्वर के साथ) करता हूं। कॉलबैक फ़ंक्शन में मैं सर्वर से परिणाम से इंकपेंटर ऑब्जेक्ट्स बना रहा हूं। इसके लिए चलने वाले थ्रेड को एसटीए होना आवश्यक है, जो स्पष्ट रूप से वर्तमान में नहीं है। इसलिए मुझे निम्नलिखित अपवाद मिलता है:एसटीए थ्रेड में कुछ कैसे चलाएं?

असेंबली में परिभाषित 'इंकपेंटर' का उदाहरण नहीं बना सकता [..] कॉलिंग थ्रेड एसटीए होना चाहिए, क्योंकि कई UI घटकों को इसकी आवश्यकता होती है।

वर्तमान में मेरी async समारोह कॉल इस तरह है:

public void SearchForFooAsync(string searchString) 
{ 
    var caller = new Func<string, Foo>(_patientProxy.SearchForFoo); 
    caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null); 
} 

मैं कॉलबैक कैसे कर सकते हैं - एसटीए हो - जो InkPresenter निर्माण करेंगे? या एक नए एसटीए धागे में XamlReader पार्सिंग का आह्वान करें।

public void SearchForFooCallbackMethod(IAsyncResult ar) 
{ 
    var foo = GetFooFromAsyncResult(ar); 
    var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter; // <!-- Requires STA 
    [..] 
} 
+0

जो भी विधि से पहले '[STAThread]' हुआ था? हमेशा उपयुक्त नहीं है लेकिन बहुत आसान है। शायद यह 2011 तक नहीं आया था? मैंने 2011 से इसका उपयोग नहीं किया है कि मुझे याद है ... – ebyrob

उत्तर

52

तुम इतनी तरह एसटीए धागे शुरू कर सकते हैं:

Thread thread = new Thread(MethodWhichRequiresSTA); 
    thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA 
    thread.Start(); 
    thread.Join(); //Wait for the thread to end 

केवल समस्या यह है कि है अपने परिणाम वस्तु किसी भी तरह पारित किया जाना चाहिए .. आप में मानकों के साथ गुजर में उस के लिए एक निजी क्षेत्र, या गोता उपयोग कर सकते हैं धागे। यहां मैंने foo डेटा को एक निजी क्षेत्र में सेट किया है और एसटीए थ्रेड शुरू किया है ताकि inkpresenter को म्यूट कर सकें!

private var foo; 
public void SearchForFooCallbackMethod(IAsyncResult ar) 
{ 
    foo = GetFooFromAsyncResult(ar); 
    Thread thread = new Thread(ProcessInkPresenter); 
    thread.SetApartmentState(ApartmentState.STA); 
    thread.Start(); 
    thread.Join(); 
} 

private void ProcessInkPresenter() 
{ 
    var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter; 
} 

आशा है कि इससे मदद मिलती है!

+0

बहुत उपयोगी लगता है - thx! इसे मेरे कोड पर लागू करने का प्रयास करेंगे। – stiank81

+0

धन्यवाद :) अगर मुझे समस्या ठीक हो जाए तो मुझे बताएं। हम इस तकनीक का उपयोग सर्वर पर हमारे एक्सएमएल नियंत्रणों की पीएनजी छवियों को उत्पन्न करने के लिए करते हैं! – Arcturus

+0

समस्या को ठीक करने के लिए लगता है, लेकिन बस एक और समस्या से मुलाकात की। * श्वास * .. जैसे ही मुझे यहां सब कुछ मिल रहा है, के रूप में स्वीकार्य के रूप में चिह्नित किया जाएगा .. Thx! – stiank81

3

यह यूआई थ्रेड पर कॉल करने के लिए पर्याप्त होना चाहिए। इसलिए, BackgroundWorker और RunWorkerAsyncCompleted पर, आप फिर स्याही प्रस्तुतकर्ता का निर्माण कर सकते हैं।

+0

आप सही हैं। समस्या यह है कि यूआई थ्रेड पर कॉलबैक नहीं चलाया जाता है। यूआई थ्रेड एसटीए के साथ चलाया जाता है, इसलिए यूआई थ्रेड पर इसे चलाने के लिए इसे मेरे लिए हल करना चाहिए। – stiank81

11

यूआई-थ्रेड पर विधि कॉल निष्पादित करने के लिए आप Dipatcher कक्षा का उपयोग कर सकते हैं। प्रेषक थ्रेड के प्रेषक को प्राप्त करने के लिए स्थिर संपत्ति CurrentDispatcher प्रदान करता है।

यदि कक्षा का आपका ऑब्जेक्ट, जो इंकपेंटर बनाता है, UI-Thread पर बनाया गया है, तो CurrentDispatcher विधि UI-Thread के डिस्पैचर को वापस कर देता है।

डिस्पैचर पर आप थ्रेड पर निर्दिष्ट प्रतिनिधि को असीमित रूप से कॉल करने के लिए BeginInvoke-method को कॉल कर सकते हैं।

+1

डिस्पैचर। इन्वोक या BeginInvoke जाने का रास्ता है। स्वीकार्य समाधान से बहुत आसान है – GameAlchemist

1

यह एक हैक का एक सा है, लेकिन मैं XTATestRunner का प्रयोग करेंगे तो अपने कोड तरह दिखेगा:

public void SearchForFooAsync(string searchString) 
    { 
     var caller = new Func<string, Foo>(_patientProxy.SearchForFoo); 
     caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null); 
    } 

    public void SearchForFooCallbackMethod(IAsyncResult ar) 
    { 

      var foo = GetFooFromAsyncResult(ar); 
InkPresenter inkPresenter; 
      new XTATestRunner().RunSTA(() => { 
         inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter; 
        }); 
    } 
एक बोनस इसे इस तरह एसटीए (या एमटीए) में फेंक दिया अपवाद को पकड़ने के लिए धागा संभव है के रूप में

:

try{ 
new XTATestRunner().RunSTA(() => { 
         throw new InvalidOperationException(); 
        }); 
} 
catch(InvalidOperationException ex){ 
} 
संबंधित मुद्दे