An alternative to using a `StringBuilder` is using LINQ with `string.Join()`.  It's about as fast and is more concise and readable.

    public string BinarySearchSetup(long[] data, long[] searchTerms)
    {
        var resultString = "";

        var lowerBound = 0;
        var upperBound = data.Length - 1;
        var results = searchTerms.Select(x => BinarySearch(data, lowerBound, upperBound, x));
        return string.Join(" ", results);
    }

If you want to parallelize the operation, you can just call `AsParallel()` and then `AsOrdered()` to preserve order:

    var results = searchTerms
        .AsParallel()
        .AsOrdered()
        .Select(x => BinarySearch(data, lowerBound, upperBound, x));

If you want to cache the results, you can build a dictionary on the distinct elements in a similar fashion to the above LINQ query.  `AsOrdered()` is not required because it's getting stored in a dictionary.  The method will look like this:

    public string BinarySearchSetup(long[] data, long[] searchTerms)
    {
        var lowerBound = 0;
        var upperBound = data.Length - 1;
        var cache = searchTerms
            .Distinct()
            .AsParallel()
            .ToDictionary(x => x, x => BinarySearch(data, lowerBound, upperBound, x));
        var results = searchTerms.Select(x => cache[x]);
        return string.Join(" ", results);
    }