Returning the result of whichever method finishes first
Tasks can have results, you should take advantage of that, instead of assigning a local variable from a lambda. And WaitAny() returns the index of the Task that finished first. This means you can do something like:

public static bool IsPrimeHybrid(BigInteger number)
{
    var byPureCalc = Task.Run(() =&gt; IsPrimeNaive(number));
    var bySearchFirst = Task.Run(() =&gt; IsPrimeBySearch(number));
    var tasks = new[] { byPureCalc, bySearchFirst };
    int firstIndex = Task.WaitAny(tasks);
    return tasks[firstIndex].Result;
}


Also, CPU and memory are also resources that you shouldn't waste. So, you may want to cancel the slower Task, after the faster one finished. For that, you can use CancellationToken, which the two computations will periodically check (you can use ThrowIfCancellationRequested () for that):

public static bool IsPrimeHybrid(BigInteger number)
{
    var cts = new CancellationTokenSource();

    var byPureCalc = Task.Run(() =&gt; IsPrimeNaive(number, cts.Token));
    var bySearchFirst = Task.Run(() =&gt; IsPrimeBySearch(number, cts.Token));
    var tasks = new[] { byPureCalc, bySearchFirst };

    int firstIndex = Task.WaitAny(tasks);

    cts.Cancel();
    return tasks[firstIndex].Result;
}