我正在尝试使用线程从另一个类返回 DataTable,但该线程没有返回 DataTable。虽然不使用线程,但它工作正常。
public class reatail
{
DataTable order_dt = new DataTable();
public DataTable loadAllOrder()
{
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 = new DataTable();
reatail r = new reatail();
Thread t;
public void storeToStock()
{
//DataTable dy = new DataTable();
Thread th=new Thread(()=>dy=r.loadAllOrder());
th.Start();
foreach(DataRow row in dy.Rows)
{
MessageBox.Show(row[0].ToString());
}
}
}
最佳答案
您的代码中存在一些问题。
首先,您面临的问题是您正在启动一个线程,但您并没有让它完成,而是立即尝试获取结果。您需要采用某种机制来了解线程何时完成,以便能够在 UI 线程上继续工作。使用 th.Join()
并不是最好的方法,因为它会在加载数据表时锁定 UI 线程。
现在最简单的事情就是使用任务并行库 (TPL) 来固定和管理您的线程。
在我向您展示之前,我只想对其他几件事发表评论。
在您的 reatail
类中,您将 order_dt
变量作为一个字段,并且您只实例化它一次。这意味着在调用 loadAllOrder
的每个地方,您都将获得对同一个表的引用,并且该表将继续被越来越多的重复记录填满。您希望将字段移动到 loadAllOrder
方法中以防止出现这种情况。
此外,在 RecieveOrder
中,您通过实例化一个新的 DataTable
来声明 dy
,但是您随后通过调用 重新分配该变量loadAllOrder
。这是一个小小的浪费。最好保持代码干净并避免创建不必要的对象。
所以你最好这样做:
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());
}
}
这不会锁定 UI,但允许负载在后台运行。
可能更简单的替代方法是使用 async
/await
。您的 storeToStock
可以像这样简单:
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());
}
}
}
关于c# - 无法使用线程返回 DataTable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39261839/