2016-09-22 57 views
11

我有一個Silverlight 5瀏覽器應用程序。在非UI線程中創建UserControl Silverlight 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線程,以避免無效的跨線程異常?

爲了性能方面的原因,我需要多線程,因爲方法調用非常慢,UI凍結。

有沒有辦法在Silverlight中調用方法SetSyncronizationContext(這是[SecurityCritical])?

+1

所有的控件都直接在gui中看到嗎?你可以創造他們懶惰? –

+0

在「LoadSubControls」方法中,我測量排列子控件的UpdateLayout以生成圖像。你的意思是我不應該運行InitializeComponent()? – George

+0

我也想把你的方法拆分成更小的塊,並且每次你真的需要在UI中放置一個控件時,只回調到UI線程。 –

回答

3

無法避免在UI線程上創建這些控件,但是您可以利用任務並行庫(TPL)中的System.Threading.Tasks.Task來允許異步操作。

我已經能夠在Silverlight 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; 
    } 
} 

您可以沿構造函數DI路徑傳遞提供程序或使用像這樣的靜態定位符模式。

/// <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; } 
    } 
} 

現在,你應該能夠使您的通話而不會阻塞主線程和凍結UI

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(); 
      });  
     } 
    } 
} 

如果進行多次調用調度引起的任何性能問題,你可以移動而不是整個過程到一個acync呼叫。

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(); 
      }  
     }); 
    } 
} 
相關問題