1

我在多线程方面不是那么好。但这是我需要做的。

我有一个数据网格。我想要一种方法来仅用前 50 行填充数据网格。同时,我希望一个线程获取接下来的 20 行并更新数据表,以便在显示 50 行时,将接下来的 20 行附加到数据表对象。通过这种方式,我可以处理大量数据而不会让我的数据表变慢。但是我在多线程中坚持使用资源共享(共享数据表对象)。

有下面的代码

public partial class InsertAndUpdateData : Window
{
    DataTable dt = new DataTable();

    public object lockOn = new object();

    public InsertAndUpdateData()
    {
        InitializeComponent();
        Thread oThread = new Thread(new ParameterizedThreadStart(FillGrid));
        oThread.Start(dt);
        oThread.Join();

        Thread.Sleep(1000);
        oThread.Abort();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        string name = txtName.Text;
        int salary = Convert.ToInt32(txtSalary.Text);

        using (var context = new NewtonEntities())
        {
            Employee emp = new Employee();
            emp.name = name;
            emp.salary = salary;

            context.AddToEmployees(emp);
            context.SaveChanges();
        }

        FillGridLastRowInserted();
    }

    public void FillGrid(object dtx)
    {
        lock (lockOn)
        {
            dt = (DataTable)dtx;
            var db = new NewtonEntities();
            var dataTable = (from c in db.Employees
                             select new
                             {
                                 c.id,
                                 c.name,
                                 c.salary
                             }).Take(20);

            dt.Columns.Add("id", typeof(int));
            dt.Columns.Add("name", typeof(string));
            dt.Columns.Add("salary", typeof(int));

            foreach (var item in dataTable)
            {
                DataRow dr = dt.NewRow();
                dr["id"] = item.id;
                dr["name"] = item.name;
                dr["salary"] = item.salary;
                dt.Rows.Add(dr);
            }

            myGrid.ItemsSource = dt.DefaultView;
        }
    }

    public void FillGridLastRowInserted()
    {
        var db = new NewtonEntities();
        var dataTable = (from c in db.Employees
                         orderby c.id descending
                         select new
                         {
                             c.id,
                             c.name,
                             c.salary
                         }).First();

        DataRow dr = dt.NewRow();
        dr["id"] = dataTable.id;
        dr["name"] = dataTable.name;
        dr["salary"] = dataTable.salary;
        dt.Rows.Add(dr);

        myGrid.ItemsSource = dt.DefaultView;
    }
}

我在主类中有一个数据表。我希望 dt 对象由两个线程方法共享。

但是每次我遇到以下错误。

在此处输入图像描述

4

3 回答 3

0

有一个更简单的解决方案。您只需要利用 WPF DataGrid 虚拟化。

使用 Snoop 确保您的网格具有虚拟化功能:http ://snoopwpf.codeplex.com/

于 2013-01-31T03:22:25.247 回答
0

如果你想坚持使用多线程。这是另一种方式:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <ListBox x:Name="lst">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

public partial class MainWindow : Window
{
    Thread th;
    static ObservableCollection<string> data;

    public MainWindow()
    {
        InitializeComponent();

        data = new ObservableCollection<string>();
        lst.ItemsSource = data;

        th = new Thread(() =>
        {
            while (true)
            {
                Thread.Sleep(500);

                this.Dispatcher.BeginInvoke(new Action(() =>
                { data.Add("zzzzzz"); }));
            }
        });

        th.Start();
    }
}
于 2013-01-31T06:04:34.733 回答
0

您无法更新 Itemsource 的原因是 mygrid 归主线程所有,您无法从单独的线程更新主线程中存在的控件。

您应该从线程返回一个值,然后绑定 - 从线程返回一个值?

如果您只想做一些后台工作,最好使用 BackgroundWorker http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

于 2013-01-30T10:06:12.163 回答