2016-09-22 12 views
11

मेरे पास सिल्वरलाइट 5 ब्राउज़र एप्लिकेशन है।गैर-यूआई थ्रेड में उपयोगकर्ता नियंत्रण बनाएं सिल्वरलाइट 5 ब्राउज़र एप्लिकेशन

एक वर्ग

public class ActivityControl:UserControl { 

    public void LoadSubControls() { 
     //Creates Other UserControls, does calculations and is very slow..No refactoring.. 
    } 
} 

मैं इस वर्ग के कई उदाहरण बना सकते हैं और क्रम पर विधि LoadSubControls कॉल करने की आवश्यकता नहीं है।

public class BasicContainer:UserControl { 

    public void CreateMultipleActivityControls() { 

     for (int i = 0; i < 1000; i++) { 

      ActivityControl c = new ActivityControl(); ====> I need to call this in a different thread but causes Invalid Cross Thread Exception 

      c.LoadSubControls(); 
     } 
    } 
} 

क्या अवैध क्रॉस थ्रेड अपवाद से बचने के लिए एकाधिक UI थ्रेड बनाने का कोई तरीका है?

मुझे प्रदर्शन कारणों से बहुभाषी की आवश्यकता है और क्योंकि विधि कॉल बहुत धीमी है और यूआई फ्रीज है।

क्या सिल्वरलाइट में विधि SetSyncronizationContext (जो [सुरक्षा क्रिटिकल] है) कॉल करने का कोई तरीका है?

+1

क्या सभी नियंत्रण सीधे गुई में देखे जाते हैं? आप उन्हें आलसी बना सकते हैं? –

+0

"LoadSubControls" विधि में मैं एक छवि उत्पन्न करने के लिए सबस्ट्रक्शंस के अद्यतन Layout को व्यवस्थित करता हूं। क्या आपका मतलब है कि मुझे InitializeComponent() नहीं चलाना चाहिए? – George

+0

मैं आपकी विधि को छोटे टुकड़ों में विभाजित करने के लिए भी जाऊंगा और हर बार आपको ui थ्रेड पर वापस कॉल करूंगा जब आपको वास्तव में यूई में नियंत्रण रखना होगा। –

उत्तर

3

यूआई थ्रेड पर इन नियंत्रणों को बनाने से कोई परहेज नहीं है, लेकिन आप एसिंक्रोनस ऑपरेशंस की अनुमति देने के लिए टास्क समांतर लाइब्रेरी (टीपीएल) से System.Threading.Tasks.Task का लाभ उठा सकते हैं।

मैं इस तरह की संरचना के साथ चांदी की रोशनी 5 में ऐसा कुछ करने में सक्षम हूं। Caliburn.Micro के स्रोत को देखने के मूल विचार मिला।

निम्नलिखित एक सबसेट है जो आप चाहते हैं कि लागू होता है।

public interface IPlatformProvider { 
    /// <summary> 
    /// Executes the action on the UI thread asynchronously. 
    /// </summary> 
    /// <param name = "action">The action to execute.</param> 
    System.Threading.Tasks.Task OnUIThreadAsync(Action action);  
} 

यहां कार्यान्वयन है।

/// <summary> 
/// A <see cref="IPlatformProvider"/> implementation for the XAML platfrom (Silverlight). 
/// </summary> 
public class XamlPlatformProvider : IPlatformProvider { 
    private Dispatcher dispatcher; 

    public XamlPlatformProvider() { 
     dispatcher = System.Windows.Deployment.Current.Dispatcher; 
    } 

    private void validateDispatcher() { 
     if (dispatcher == null) 
      throw new InvalidOperationException("Not initialized with dispatcher."); 
    } 

    /// <summary> 
    /// Executes the action on the UI thread asynchronously. 
    /// </summary> 
    /// <param name = "action">The action to execute.</param> 
    public Task OnUIThreadAsync(System.Action action) { 
     validateDispatcher(); 
     var taskSource = new TaskCompletionSource<object>(); 
     System.Action method =() => { 
      try { 
       action(); 
       taskSource.SetResult(null); 
      } catch (Exception ex) { 
       taskSource.SetException(ex); 
      } 
     }; 
     dispatcher.BeginInvoke(method); 
     return taskSource.Task; 
    } 
} 

आप या तो नीचे निर्माता डि मार्ग जाना प्रदाता में पास या इस तरह एक स्थिर लोकेटर पैटर्न का उपयोग करने के लिए कर सकता है।

/// <summary> 
/// Access the current <see cref="IPlatformProvider"/>. 
/// </summary> 
public static class PlatformProvider { 
    private static IPlatformProvider current = new XamlPlatformProvider(); 

    /// <summary> 
    /// Gets or sets the current <see cref="IPlatformProvider"/>. 
    /// </summary> 
    public static IPlatformProvider Current { 
     get { return current; } 
     set { current = value; } 
    } 
} 

अब आप अगर डिस्पैचर करने के लिए कई कॉल करने के लिए किसी भी प्रदर्शन के मुद्दों की वजह से आप के बजाय पूरी प्रक्रिया को स्थानांतरित कर सकता है मुख्य थ्रेड अवरुद्ध और ठंड यूआई

public class BasicContainer : UserControl { 
    public async Task CreateMultipleActivityControls() { 
     var platform = PlatformProvider.Current; 
     for (var i = 0; i < 1000; i++) { 
      await platform.OnUIThreadAsync(() => {  
       var c = new ActivityControl();  
       c.LoadSubControls(); 
      });  
     } 
    } 
} 

के बिना अपने कॉल करने के लिए सक्षम होना चाहिए एक एसीएनसी कॉल करने के लिए।

public class BasicContainer : UserControl { 
    public async Task CreateMultipleActivityControls() { 
     var platform = PlatformProvider.Current; 
     await platform.OnUIThreadAsync(() => { 
      for (var i = 0; i < 1000; i++) {      
       var c = new ActivityControl();  
       c.LoadSubControls(); 
      }  
     }); 
    } 
} 
संबंधित मुद्दे