There are a few things going wrong in your code.
To start with the issue you're facing is that you're starting a thread, but instead of allowing it to finish you're immediately trying to get the result. You need to employ some mechanism to know when the thread is finished to be able to continue the work back on the UI thread. Using th.Join() isn't the best approach as it locks up the UI thread while the data table is loaded.
The easiest thing these days is to employ the Task Parallel Library (TPL) to pin up and manage your threads for you.
Before I show you how I just wanted to comment on a couple of other things.
In your reatail class you have the order_dt variable as a field and you instantiate it only once. This means that in every place that loadAllOrder is called you'll get a reference to the same table and that table will continue to get filled up with more and more duplicate records. You want to move the field inside the loadAllOrder method to prevent that.
Also, in RecieveOrder you declare dy by instantiated a new DataTable, but you then reassign that variable with your call to loadAllOrder. That's a small waste. It's much better to keep your code clean and avoid unnecessary objects being created.
So you're better off doing this:
public class reatail { public DataTable loadAllOrder() { DataTable order_dt = new DataTable(); OleDbConnection co = new OleDbConnection(); co.ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + sd + "bowoni.accdb"; string loadAll = "select * from allorder"; co.Open(); OleDbCommand cc = new OleDbCommand(loadAll, co); OleDbDataAdapter ad = new OleDbDataAdapter(cc); ad.Fill(order_dt); return order_dt; } } public partial class RecieveOrder : Form { DataTable dy; reatail r = new reatail(); public void storeToStock() { Task .Run(() => r.loadAllOrder()) .ContinueWith(t => { dy = t.Result; foreach (DataRow row in dy.Rows) { MessageBox.Show(row[0].ToString()); } }, TaskScheduler.FromCurrentSynchronizationContext()); } }
This doesn't lock up the UI, yet allows the load to run in the background.
The alternative that might even be simpler is to use async/await. Your storeToStock could be as simple as:
public partial class RecieveOrder : Form { DataTable dy; reatail r = new reatail(); public async void storeToStock() { dy = await Task.Run(() => r.loadAllOrder()); foreach (DataRow row in dy.Rows) { MessageBox.Show(row[0].ToString()); } } }