In the first part of this series, we covered how to build a task sequence. In this part I’m going to show you how to start the sequence from a specific task, run tasks conditionally and pass parameters between tasks.
- Part 1: How to build a task sequence
- Part 2: Start with a specific task, conditional tasks and passing parameters
- Part 3: Build a task sequence using Prism
Starting from an specific task
There are scenarios where we want the task sequence to start from a task. For example, you want to start in the HomePage and skip all the previous tasks.

To achieve it, create an overload for StartAsync method of the StartupTaskSequencer class that will take an IStartupTask as parameter. This task will be the starting task in the sequence, so all the tasks previous to this one will be skipped.
public interface IStartupTaskSequencer | |
{ | |
Task StartAsync(); | |
Task StartAsync(IStartupTask task); | |
} |
public class StartupTaskBuilder | |
{ | |
... | |
private class StartupTaskSequencer : IStartupTaskSequencer | |
{ | |
public StartupTaskSequencer(Queue<IStartupTask> tasks) => _tasks = tasks; | |
public async Task StartAsync(IStartupTask task) | |
{ | |
foreach (var next in _tasks.SkipWhile(x => x != task)) | |
{ | |
if (await next.CanRunAsync()) | |
{ | |
await next.RunAsync(); | |
} | |
} | |
} | |
public Task StartAsync() => StartAsync(_tasks.FirstOrDefault()); | |
private readonly Queue<IStartupTask> _tasks; | |
} | |
} |
In the SplashPage, when calling the StartAsync method specify which task we want to start from.
public partial class SplashPage : ContentPage | |
{ | |
IStartupTaskSequencer sequencer; | |
HomePage homePage = new HomePage(); | |
public SplashPage() | |
{ | |
InitializeComponent(); | |
sequencer = new StartupTaskBuilder() | |
.Add(new SimulateDownloadDataStartupTask()) | |
.Add(new UpdateVersionStartupTask()) | |
.Add(new OnboardingPage()) | |
.Add(new PermissionRequestPage()) | |
.Add(homePage) | |
.Add(new AdvertisingPage()) | |
.Add(new HomePage()) | |
.Build(); | |
} | |
protected override async void OnAppearing() | |
{ | |
base.OnAppearing(); | |
await sequencer.StartAsync(homePage); | |
} | |
} |
Result:

Run tasks conditionally
Is very common to run tasks only if it meets certain conditions. For example, if you have an application that shows an advertisement task only if the user is using the free version otherwise this task should be skipped.

To represent this scenario, let’s add a property for the version type in the App class.
public partial class App : Application | |
{ | |
public static VersionType VersionType => VersionType.Paid; | |
public App () | |
{ | |
InitializeComponent(); | |
MainPage = new SplashPage(); | |
} | |
} | |
public enum VersionType | |
{ | |
Free, | |
Paid | |
} |
In the AdvertisingPage by overriding the CanRunAsync method, evaluate if VersionType is free. If so task should run, otherwise will be skipped.
public partial class AdvertisingPage : StartupPage | |
{ | |
public AdvertisingPage() | |
{ | |
InitializeComponent(); | |
} | |
protected override Task<bool> CanRunAsync() => Task.FromResult(App.VersionType == VersionType.Free); | |
} |
Passing parameters
In certain use cases we might need the output of the previous task to be the input of the next task to run. For example, you want to pass the username from the LoginPage task to the HomePage task.
To achieve it, let’s create a class to represent parameters:
public interface IStartupTaskParameters : IDictionary<string, object>{} | |
public class StartupTaskParameters : Dictionary<string, object>, IStartupTaskParameters | |
{ | |
public static IStartupTaskParameters None => _none ??= new StartupTaskParameters(); | |
private static IStartupTaskParameters _none; | |
} |
Modify the IStartupTask to support parameters:
public interface IStartupTask | |
{ | |
Task<bool> CanRunAsync(); | |
Task<IStartupTaskParameters> RunAsync(IStartupTaskParameters parameters); | |
} |
Modify StartupTaskSequencer class to pass parameters of previous task to the next running task
private class StartupTaskSequencer : IStartupTaskSequencer | |
{ | |
public StartupTaskSequencer(Queue<IStartupTask> tasks) => _tasks = tasks; | |
public async Task StartAsync(IStartupTask task, IStartupTaskParameters parameters = null) | |
{ | |
parameters ??= StartupTaskParameters.None; | |
foreach (var next in _tasks.SkipWhile(x => x != task)) | |
{ | |
if (await next.CanRunAsync()) | |
{ | |
parameters = await next.RunAsync(parameters); | |
} | |
} | |
} | |
} |
Pass the parameters in the CompleteAsync method of the previous task:
public partial class LoginPage : StartupPage | |
{ | |
public ICommand NextCommand { get; } | |
public LoginPage() : base() | |
{ | |
InitializeComponent(); | |
NextCommand = new Command(async() => | |
{ | |
await CompleteAsync(new StartupTaskParameters() | |
{ | |
{"Name" , userNameEntry.Text } | |
}); | |
}); | |
} | |
} |
Evaluate and consume the parameters in the next task.
public partial class HomePage : TabbedPage, IStartupTask | |
{ | |
public HomePage() | |
{ | |
InitializeComponent(); | |
} | |
public Task<bool> CanRunAsync() => Task.FromResult(true); | |
public async Task<IStartupTaskParameters> RunAsync(IStartupTaskParameters parameters) | |
{ | |
if (parameters.TryGetValue("Name", out var name)) | |
{ | |
await App.Current.MainPage.DisplayAlert("Welcome!", name?.ToString(), "Ok"); | |
} | |
await App.Current.MainPage.Navigation.PushModalAsync(this); | |
return StartupTaskParameters.None; | |
} | |
} |
Result:

Stay tuned for the next part of this series where you’ll see how to build a task sequence using Prism.
Check the full source code here.
Happy Task Sequence!