Podziel dane na mniejsze porcje, powiedzmy od 100 do 1000 wierszy na raz. Jeśli siatka WPF jest databound do zbierania danych, a kolekcja jest obserwowalna kolekcja (implementuje INotifyCollectionChanged), WPF automatycznie zaktualizuje wyświetlanie, gdy nowe dane zostaną dodane do kolekcji.
Należy również rozważyć użycie wirtualnych kontrolek lub siatek list w połączeniu ze źródłami danych stronicowania, aby wczytać tylko te dane, które są aktualnie wyświetlane na ekranie (zamiast 1,2 mln wierszy danych w pamięci). Spowoduje to wykonanie "chunkingu" dla ciebie i umożliwi prezentowanie w zasadzie nieskończonej ilości danych użytkownikowi z bardzo małym zużyciem pamięci lub opóźnieniem sieci.
Sprawdź ten artykuł na SO pobierania danych asynchronicznie na wirtualnym polu listy: How do I populate a ListView in virtual mode asynchronously?