2013-03-12 10 views
12

मैंने GUI थ्रेड पर स्विच करने के लिए आज स्विचटो विधि का उपयोग करने का प्रयास किया, और पाया कि जिस उदाहरण से मैंने इसे उठाया है वह काम नहीं करता है, क्योंकि बस विधि नहीं है।Async CTP/रिलीज़ से "स्विचटो" क्यों हटाया गया था?

कारण है कि हम यह से छुटकारा मिला था, क्योंकि यह इतना खतरनाक था:

मैं तो इस blurb here पाया। वैकल्पिक TaskEx.Run के अंदर अपना कोड ऊपर बंडल है ...

मेरा प्रश्न केवल यह है: क्यों यह खतरनाक था? इसका उपयोग किस विशिष्ट खतरे का कारण होगा?

ध्यान दें कि ने उस पोस्ट को बाकी पढ़ा, इसलिए मुझे समझ में आता है कि यहां तकनीकी सीमाएं हैं। मेरा सवाल अभी भी है, अगर मुझे इस बारे में पता है, तो यह खतरनाक क्यों है?

मैं मुझे निर्दिष्ट कार्यक्षमता देने के लिए सहायक तरीकों को पुन: कार्यान्वित करने पर विचार कर रहा हूं, लेकिन अगर मूलभूत रूप से टूटा हुआ कुछ है, तो किसी ने फैसला किया कि यह खतरनाक था, मैं ऐसा नहीं करता।

public static class ContextSwitcher 
{ 
    public static ThreadPoolContextSwitcher SwitchToThreadPool() 
    { 
     return new ThreadPoolContextSwitcher(); 
    } 

    public static SynchronizationContextSwitcher SwitchTo(this SynchronizationContext synchronizationContext) 
    { 
     return new SynchronizationContextSwitcher(synchronizationContext); 
    } 
} 

public class SynchronizationContextSwitcher : INotifyCompletion 
{ 
    private readonly SynchronizationContext _SynchronizationContext; 

    public SynchronizationContextSwitcher(SynchronizationContext synchronizationContext) 
    { 
     _SynchronizationContext = synchronizationContext; 
    } 

    public SynchronizationContextSwitcher GetAwaiter() 
    { 
     return this; 
    } 

    public bool IsCompleted 
    { 
     get 
     { 
      return false; 
     } 
    } 

    public void OnCompleted(Action action) 
    { 
     _SynchronizationContext.Post(_ => action(), null); 
    } 

    public void GetResult() 
    { 
    } 
} 

public class ThreadPoolContextSwitcher : INotifyCompletion 
{ 
    public ThreadPoolContextSwitcher GetAwaiter() 
    { 
     return this; 
    } 

    public bool IsCompleted 
    { 
     get 
     { 
      return false; 
     } 
    } 

    public void OnCompleted(Action action) 
    { 
     ThreadPool.QueueUserWorkItem(_ => action(), null); 
    } 

    public void GetResult() 
    { 
    } 
} 

यह मैं इस तरह कोड लिखने की अनुमति होगी:

public async void Test() 
{ 
    await ContextSwitcher.SwitchToThreadPool(); // ensure we're not bogging down the UI thread 
    // do some heavy processing 
    await _UIContext.SwitchTo(); // presumably saved from the main thread 
    // update UI with new data 
} 
+0

हां।अब यह काफी पुराना धागा है! मैं कभी माइक्रोसॉफ्ट के कभी-कभी "यह आपके अपने अच्छे" तर्क के प्रशंसक नहीं रहा हूं। –

+1

मैंने तब से 'कार्य का इंतजार करने के लिए स्विच किया है। रुन (async() => {})' - कुछ खाली खतरों से बचने के लिए नहीं, बल्कि इसलिए कि मुझे लगता है कि इसे पढ़ना आसान है। मुझे लगता है कि 'SwitchTo()' को कार्यान्वित करने के तरीके के बारे में आपका विचार ध्वनि है, हालांकि। –

+0

'async() => {} 'वाक्यविन्यास के बारे में नहीं पता था, आगे की जांच की आवश्यकता है, धन्यवाद! –

उत्तर

6

स्टीफन Toub पर कुछ और जानकारी है

विशेष रूप से, बहुत भोलेपन से, यहाँ मैं कैसे आवश्यक तरीकों को लागू करने पर विचार करेगा है this thread में तर्क।

संक्षेप में, यह दो कारणों के लिए एक अच्छा विचार नहीं है:

  1. यह असंरचित कोड बढ़ावा देता है। यदि आपके पास "भारी प्रसंस्करण" है जो आपको करने की ज़रूरत है, तो इसे Task.Run में रखा जाना चाहिए। इससे भी बेहतर, अपने यूआई तर्क से अपने व्यापार तर्क को अलग करें।
  2. त्रुटि प्रबंधन और (कुछ) निरंतरता अज्ञात संदर्भ में चलती है। catch/finallyTest में ब्लॉक थ्रेड पूल या UI संदर्भ में चलने को संभालने की आवश्यकता होगी (और यदि वे थ्रेड पूल संदर्भ में चल रहे हैं, तो वे UI संदर्भ पर कूदने के लिए SwitchTo का उपयोग नहीं कर सकते हैं)। इसके अलावा, जब तक कि आप await लौटे Task आप ठीक होना चाहिए (await निरंतरता संदर्भ यदि आवश्यक हो तो सही कर देंगे), लेकिन अगर आप स्पष्ट ContinueWith निरंतरता कि ExecuteSynchronously का उपयोग किया है, तो वे catch/finally ब्लॉकों के रूप में एक ही समस्या है ।

संक्षेप में, कोड SwitchTo के बिना क्लीनर और अधिक अनुमानित है।

+0

ठीक है, जो उस पर अधिक प्रकाश डालता है। यह अभी भी अजीब दिखता है, यह पोस्ट कहने के लिए, यह अज्ञात संदर्भों के साथ सभी तरह की समस्याओं का निर्माण करता है, और फिर यह दिखाने के लिए चलता है कि वैसे भी समर्थन को कैसे कार्यान्वित किया जाए। –

+0

@ LasseV.Karlsen मुझे लगता है कि नेट के डेवलपर्स के लिए रवैया असामान्य नहीं है। जैसा कि मैं इसे समझता हूं, वे कुछ कह रहे हैं "अगर हमने यह सुविधा प्रदान की है, तो लोग सोचेंगे कि इसका उपयोग करना ठीक है, इसलिए वे अक्सर इसका इस्तेमाल करेंगे, जो एक बुरी चीज है। लेकिन अगर यह कुछ ब्लॉग पर पोस्ट किया गया है, तो उन्हें केवल तभी उपयोग करने की संभावना है जब उन्हें वास्तव में इसकी आवश्यकता हो और समझें कि वास्तव में क्या चल रहा है, जो ठीक है। " – svick

+0

@svick मैं इसे स्वीकार कर सकता हूं :) –

2

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

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