I would create an event and waited on this event (probably besides few other objects) in the thread routine instead of the KeDelayExecutionThread. Once I need to unload driver I would signal that event so the thread routine left waiting and called PsTerminateSystemThread. At the same time DriverUnload can wait for the thread to exit by waiting on the thread object.
Alternatively (less modifications in your code but not that nice) you can create some global variable and check its state in your Func:
void Func(PVOID a)
delay.QuadPart = SEC(1);
DbgPrint(">> thread message");
In DriverUnload set the g_bLeaveThread to non-zero value and wait for the thread to exit (KeWaitForSingleObject on the thread object).