UI 스레드에서 이러한 컨트롤을 만들지 않아도되지만 비동기 작업을 허용하기 위해 TPL (작업 병렬 라이브러리)의 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;
}
}
프로듀서를 전달하기 위해 생성자 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();
}
});
}
}
gui에서 모든 컨트롤을 직접 볼 수 있습니까? 게으르게 만들 수 있니? –
"LoadSubControls"메서드에서 이미지를 생성하기 위해 하위 컨트롤의 Measure LayoutLayout을 측정합니다. InitializeComponent()를 실행해서는 안된다는 뜻입니까? – George
나는 당신의 메소드를 더 작은 덩어리로 분할하고 UI에 컨트롤을 배치해야 할 때마다 UI 스레드로만 콜백 할 것입니다. –