c# - 无法使用线程返回 DataTable

标签 c# multithreading

我正在尝试使用线程从另一个类返回 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/

相关文章:

multithreading - OpenMP while 循环

c++ - 如何复制/移动包含互斥锁的类

c++ - 影响性能之前 Unix 中的线程限制

c++ - 如何正确地将此指针传递给 std::thread

c# - "Server cannot accept argument"Azure VM 中 IIS 中的 FTP 服务器引发异常

C# IList更新问题

c# - 为什么 TextInfo.ToTitleCase 在字母全部为大写的字符串上不能正常工作?

c# - 无需在客户端安装 mysql 连接器即可将应用程序转换为工作

multithreading - Ada95 中的线程和信号量

c# - 使用 System.IdentityModel.Tokens.Jwt 从 1.1 迁移到 2.0 后,JWTAuthentication 在 asp.net core 2.0 中不起作用 - 5.1.4 更新