아래 코드를 사용하면 최종 ContinueWith에서 최종 UI 업데이트가 수행되지 않습니다. 나는 이것이 내가 끝내주는 대기 (Wait) 때문이라고 생각한다.작업 흐름 시퀀스가 잘못되었습니다.
내가 그 이유는 Wait이 없기 때문에 메서드가 백그라운드에서 생성 된 완성되기 전에 IDataProvider를 반환하기 때문입니다.
누군가 내가이 권리를 얻을 수 있도록 도와 줄 수 있습니까?
건배,
Berryl
private IDataProvider _buildSQLiteProvider()
{
IDataProvider resultingDataProvider = null;
ISession session = null;
var watch = Stopwatch.StartNew();
var uiContext = TaskScheduler.FromCurrentSynchronizationContext();
// get the data
var buildProvider = Task.Factory
.StartNew(
() =>
{
// code to build it
});
// show some progress if we haven't finished
buildProvider.ContinueWith(
taskResult =>
{
// show we are making progress;
},
CancellationToken.None, TaskContinuationOptions.None, uiContext);
// we have data: reflect completed status in ui
buildProvider.ContinueWith(
dataProvider =>
{
// show we are finished;
},
CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, uiContext);
try {
buildProvider.Wait();
}
catch (AggregateException ae)
{
foreach (var e in ae.InnerExceptions)
Console.WriteLine(e.Message);
}
Console.WriteLine("Exception handled. Let's move on.");
CurrentSessionContext.Bind(session);
return resultingDataProvider;
}
====
은
나는 문제가 UI 스레드 이야기를 가지고 있지 않다 명확합니다. 첫 번째 업데이트는 계속 진행됩니다. 내가 겪고있는 문제는 마지막 업데이트와 데이터 제공 업체의 반환시기입니다.
나는이 게시물의 잡음 수준을 줄이고 작업 시퀀싱에 초점을 맞추기 위해 코드를 주석 처리했다.
====
확인, 작업은 나에게 TPL을 보증 같은이 코드는 보이지 않는
private void _showSQLiteProjecPicker()
{
var watch = Stopwatch.StartNew();
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
ISession session = null;
// get the data
var buildProvider = Task.Factory.StartNew(
() =>
{
var setProgress = Task.Factory.StartNew(
() =>
{
IsBusy = true;
Status = string.Format("Fetching data...");
},
CancellationToken.None, TaskCreationOptions.None, uiScheduler);
var provider = new SQLiteDataProvider();
session = SQLiteDataProvider.Session;
return provider;
});
buildProvider.ContinueWith(
buildTask =>
{
if(buildTask.Exception != null) {
Console.WriteLine(buildTask.Exception);
}
else {
Check.RequireNotNull(buildTask.Result);
Check.RequireNotNull(session);
_updateUiTaskIsComplete(watch);
CurrentSessionContext.Bind(session);
var provider = buildTask.Result;
var dao = provider.GetActivitySubjectDao();
var vm = new ProjectPickerViewModel(dao);
_showPicker(vm);
}
},
CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, uiScheduler);
}
BGW는 자체적으로 문제를 제기하지만이 시나리오에서는 괜찮을 것이라고 동의합니다. 나는 TPL이 더 쉽고 유연해질 것이라 생각한다. 그리고이 질문은 TPL 사용에 관한 것이지 진척 상황을보고하는 방법이 아니다. 더 중요한 것은 코드를 살펴보면 WPF (좋은 점)에 의존하지 않고 UI 컨텍스트를 캡처하고 ContinueWith *가 "UI를 업데이트합니다."라고 말합니다. 건배 – Berryl
@Statis. 나는 그것을 원한다. 네, 끝에서의 기다림은 패배자였습니다. 첫 번째 연속과 마찬가지로 진행을 업데이트합니다. 마지막 연속은 개념적으로 정확했습니다. 첫 번째 연속 대신에 새로운 작업이 필요합니다. 당신과 Nicholas가 제안 했음)하지만 원래 태스크 내부에 중첩되어 있어야하며 UI 스레드가 있어야합니다 .TPL을 배우고 비동기 프로그래밍에 대한 접근 방식을 표준화하기를 원할뿐 아니라 결국에는 다른 태스크를 피킹하고 싶습니다. BGW에 고통 스러울 것입니다. 도와 주셔서 감사합니다. – Berryl