Я наблюдаю странное поведение, связанное с async / await, но не могу его объяснить.
Вот основные c logi c:
public async Task Init(UI.INavigable NavigateFrom) <-- Starts from here
{
await NavigateFrom.Navigate<UI.Pages.Page>(await Common.CreateDrillInNavigationTransitionInfo(), async (Page) =>
{
// ...
m_SelectPage.OnCategorySelected += OnCategorySelected;
// ... (including more awaits)
await OnModelUpdated();
return Page;
});
}
private async Task OnModelUpdated()
{
await m_SelectPage.DataUpdated(...);
}
public async Task DataUpdated(...)
{
try
{
m_Initializing = true;
await Common.RunUiTask(async () =>
{
// ... (including more awaits)
await Task.Run(async () =>
{
// ... (including more awaits)
System.Diagnostics.Debug.Print("DataUpdated: Calling CategorySelected\n");
await OnCategorySelected(await GetSelectedCategory());
});
});
}
finally
{
m_Initializing = false;
}
}
private async Task OnCategorySelected(Model.Category Category)
{
Debug.Print("OnCategorySelected start\n");
var Adaptor = new Model.Adaptor(...);
var p = new InfoPage(m_ActualApp, Adaptor);
Debug.Print("OnCategorySelected navigate\n");
await p.Init(SelectPage);
Debug.Print("OnCategorySelected end\n");
}
public async Task Init(UI.INavigable NavigateFrom)
{
Debug.Print("Init start\n");
await NavigateFrom.Navigate<UI.Pages.InfoPage>(await Common.CreateDrillInNavigationTransitionInfo(), async (Page) =>
{
Debug.Print("Init lambda\n");
// ...
Debug.Print("Init lambda update\n");
await m_InfoPage.Updated(...);
Debug.Print("Init lambda end\n");
return Page;
});
Debug.Print("Init end\n");
}
И вот результат одного прогона (он не каждый раз ведет себя одинаково):
DataUpdated: Calling CategorySelected
OnCategorySelected start
OnCategorySelected navigate
Init start
OnCategorySelected start
OnCategorySelected navigate
Init start
Init lambda
Init lambda update
OnCategorySelected start
OnCategorySelected navigate
Init start
Init lambda end
Init end
OnCategorySelected end
Init lambda
Init lambda update
Init lambda
Init lambda update
Init lambda end
Init end
OnCategorySelected end
Init lambda end
Init end
OnCategorySelected end
Как ясно видно из вывода, кажется, что как только он попадает в await в Init или он попадает в await внутри лямбды в функции Init, он приостанавливается (что правильно), но затем перезапускается обратно в функции OnCategorySelected без видимой причины.
Я не могу объяснить, что происходит. Это должно произойти только один раз, поскольку нет кода, который снова вызывает OnCategorySelected. Есть идеи?
Для справки, вот служебные функции, которые я использую на случай, если в них есть какие-то странности:
public static async Task<DrillInNavigationTransitionInfo> CreateDrillInNavigationTransitionInfo()
{
return await Common.RunUiTask(async () =>
{
return await Task.FromResult(new DrillInNavigationTransitionInfo());
});
}
public static class Common
{
public static async Task<T> RunUiTask<T>(Func<Task<T>> F)
{
return await CoreApplication.MainView.CoreWindow.Dispatcher.RunTaskAsync(async () =>
{
return await F();
});
}
}
public static class DispatcherTaskExtensions
{
public static async Task<T> RunTaskAsync<T>(this CoreDispatcher Dispatcher, CoreDispatcherPriority Priority, Func<Task<T>> Func)
{
var TaskCompletionSource = new TaskCompletionSource<T>();
await Dispatcher.RunAsync(Priority, async () =>
{
try
{
var R = await Func();
TaskCompletionSource.SetResult(R);
}
catch (Exception ex)
{
TaskCompletionSource.SetException(ex);
}
});
return await TaskCompletionSource.Task;
}
public static async Task<T> RunTaskAsync<T>(this CoreDispatcher Dispatcher, Func<Task<T>> Func)
{
return await RunTaskAsync(Dispatcher, CoreDispatcherPriority.Normal, Func);
}
}