Используйте Parallel.For вместо foreach, так минимум уменьшите выполнение 2 раза.
Вот пример и не удивляйтесь, что числа идут в разнобой.

И что-то я не совсем понял где у вас там асинхронность, вроде же все выполняется в GUI потоке, если нужен полный асинхрон, то лучше использовать Task.Run(() => { ... }); для каждого IP.
Ах да, если написать методу async, это не значит, что он асинхронный.
Чтобы он был полностью асинхронным нужна примерно такая конструкция: