1

私はマルチスレッドが得意ではありません。しかし、これは私がしなければならないことです。

私はデータグリッドを持っています。データグリッドを最初の 50 行だけで埋めるメソッドが 1 つ必要です。その間、スレッドで次の 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 オブジェクトを 2 つのスレッド化されたメソッドで共有したいと考えています。

しかし、毎回次のエラーが発生します。

ここに画像の説明を入力

4

3 に答える 3

0

Itemsourceを更新できない理由は、mygridがメインスレッドによって所有されており、メインスレッドに存在するコントロールを別のスレッドから更新できないためです。

スレッドから値を返し、バインドする必要があります-スレッドから値を返し ますか?

バックグラウンド作業だけを行う場合は、BackgroundWorkerhttp ://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspxを使用することをお勧めします。

于 2013-01-30T10:06:12.163 に答える
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 に答える