If the GUI locks up, it's better to do the calculations on a seperate thread.
.NET has easy mechanisms for this. You will have to take care of the synchronization between the GUI thread and the 'worker' thread. Indead,
passing arguments to the worker thread is not always an easy thing to do, and you'll need synchronization for this (most of the time I use the AutoResetEvent class for this)
A simple example for getting started:

VB Code:
  1. Imports System
  2. Imports System.Threading
  3.  
  4. ' Simple threading scenario:  Start a Shared method running
  5. ' on a second thread.
  6. Public Class ThreadExample
  7.     ' The ThreadProc method is called when the thread starts.
  8.     ' It loops ten times, writing to the console and yielding
  9.     ' the rest of its time slice each time, and then ends.
  10.     Public Shared Sub ThreadProc()
  11.         Dim i As Integer
  12.         For i = 0 To 9
  13.             Console.WriteLine("ThreadProc: {0}", i)
  14.             ' Yield the rest of the time slice.
  15.             Thread.Sleep(0)
  16.         Next
  17.     End Sub
  18.  
  19.     Public Shared Sub Main()
  20.         Console.WriteLine("Main thread: Start a second thread.")
  21.         ' The constructor for the Thread class requires a ThreadStart
  22.         ' delegate.  The Visual Basic AddressOf operator creates this
  23.         ' delegate for you.
  24.         Dim t As New Thread(AddressOf ThreadProc)
  25.         ' Start ThreadProc.  On a uniprocessor, the thread does not get
  26.         ' any processor time until the main thread yields.  Uncomment
  27.         ' the Thread.Sleep that follows t.Start() to see the difference.
  28.         t.Start()
  29.         'Thread.Sleep(0)
  30.  
  31.         Dim i As Integer
  32.         For i = 1 To 4
  33.             Console.WriteLine("Main thread: Do some work.")
  34.             Thread.Sleep(0)
  35.         Next
  36.  
  37.         Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends.")
  38.         t.Join()
  39.         Console.WriteLine("Main thread: ThreadProc.Join has returned.  Press Enter to end program.")
  40.         Console.ReadLine()
  41.     End Sub
  42. End Class

You might also use the ThreadPool class

VB Code:
  1. Imports System
  2. Imports System.Threading
  3.  
  4. Public Class Example
  5.     Public Shared Sub Main()
  6.         ' Queue the task.
  7.         ThreadPool.QueueUserWorkItem( _
  8.             New WaitCallback(AddressOf ThreadProc) _
  9.             )
  10.         ' Note that you do not have to create the WaitCallback delegate
  11.         ' explicitly in Visual Basic.  The following line also queues
  12.         ' the task:
  13.         'ThreadPool.QueueUserWorkItem(AddressOf ThreadProc)
  14.        
  15.         Console.WriteLine("Main thread does some work, then sleeps.")
  16.         ' If you comment out the Sleep, the main thread exits before
  17.         ' the thread pool task runs.  The thread pool uses background
  18.         ' threads, which do not keep the application running.  (This
  19.         ' is a simple example of a race condition.)
  20.         Thread.Sleep(1000)
  21.  
  22.         Console.WriteLine("Main thread exits.")
  23.     End Sub
  24.  
  25.     ' This thread procedure performs the task.
  26.     Shared Sub ThreadProc(stateInfo As Object)
  27.         ' No state object was passed to QueueUserWorkItem, so
  28.         ' stateInfo is null.
  29.         Console.WriteLine("Hello from the thread pool.")
  30.     End Sub
  31. End Class

Notes : here you can use the stateInfo argument to pass your own data.