You can't stop the UI thread doing a long operation with a button, because the button click will not be processed until the long running job has completed.
The only way to do it is to move the code to a different thread, but then you can't access any controls at all on the new thread or you will get the cross threading excpetion you have seen.
There are two way round that:
1) Use a BackgroundWorker class
] to handle the long running code, and pass the control update data back to the UI thread via the Progress reporting facility of the BackgroundWorker. This is normally pretty simple to do, and I do it a lot!
2) Invoke the control
] to do the update which moves the update code back to the UI thread. That's messy, and can be cumbersome to read in code.