Я думаю, вам нужно зарегистрировать функцию callback перед началом задачи. Ваш код должен выглядеть примерно так.
В методе Page_Load вы должны сохранить CancellationTokenSource в сеансе пользователя.
public partial class Contact : Page
{
    CancellationTokenSource tokenSource = new CancellationTokenSource();
    protected void Page_Load(object sender, EventArgs e)
    {
        if (HttpContext.Current.Session["Cart"] != null)
        {
            tokenSource = HttpContext.Current.Session["Cart"] as CancellationTokenSource;
        }
        else
        {
            HttpContext.Current.Session.Add("Cart", new CancellationTokenSource());
            tokenSource = HttpContext.Current.Session["Cart"] as CancellationTokenSource;
        }
    }
    protected void btnExportExcel_Click(object sender, EventArgs e)
    {
        CancellationToken cToken = tokenSource.Token;
        cToken.Register(() => cancelNotification());
        Task.Factory.StartNew(() =>
        {
        // do some heavy work here
        GenerateReport(sender, cToken);
            if (cToken.IsCancellationRequested)
            {
            // another thread decided to cancel
            return;
            }
        }, cToken);
    }
    private void GenerateReport(object sender, CancellationToken ct)
    {
        var students = _context.Students.ToList();
        var courses = _context.Courses.ToList();
        var teachers = _context.Teachers.ToList();
        // Todo: Use above data to Generate Excel Report
        // Just to Simulate Export to excel
        Thread.Sleep(7000);
    }
    protected void btnCancel_Click(object sender, EventArgs e)
    {
        tokenSource.Cancel();
    }
    private static void cancelNotification()
    {
        // Why never called ?
    }
}
                Ваш второй вопрос.
Вы можете загрузить список async. С помощью метода ToListAsync()и там вы можете дать свой canalactiontoken в нем.
Документация Microsoft
Надеюсь, это поможет вам?