Laden...

Bindingsource in extra Thread füllen

Erstellt von itstata vor 15 Jahren Letzter Beitrag vor 15 Jahren 2.807 Views
I
itstata Themenstarter:in
302 Beiträge seit 2008
vor 15 Jahren
Bindingsource in extra Thread füllen

Hallo,
folgenes Problem.
Ich habe ein Steuerelement(listbox), das Daten aus der Bindingsource anzeigt. Da meine Applikation durch die vielzahl der Daten etwas hängt wollte ich dies in einem seperatem Thread realisieren.
Erste Frage: macht dies sinn oder geht es auch eleganter?

Leider scheint mein hauptthread aber nicht mitzubekommen, dass schon sämtliche Daten in der Bindingsource geladen sind und die listbox zeigt weiterhin nichts an.
Hat jemand eine Idee wie ich das realisieren kann?

wenn ich manuell
listbox.datasource=null;
listbox.datasource=bs;
schreibe gehts

  
 public partial class Form1 : Form
    {
        private BindingSource bs = new BindingSource();
        private Thread thread;

        public Form1()
        {
            InitializeComponent();
            this.listBox1.DataSource = bs;
            ThreadStart ts = new ThreadStart(BindData);
            thread = new Thread(ts);
            thread.Start();
        }

        private void BindData()
        {
            using (Entities entities = new Entities())
            {
                bs.DataSource = from f in entities.Firma
                                select new { f.ID, f.Name };

                Console.WriteLine("Fertig");
            }
        }
    }
49.485 Beiträge seit 2005
vor 15 Jahren

Hallo itstata,

auch beim Zugriff auf die BindingSource gilt: [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke)

herbivore

5.299 Beiträge seit 2008
vor 15 Jahren

Hi istata!

Neulich erst habich entdeckt, daß BindingList<T> die Möglichkeit bietet, die Daten voll umzukrempeln, ohne eine Aktualisierung auszulösen. Da gibts den Konstruktor


public BindingList(System.Collections.Generic.IList<T> list)

Da kannste die InnerList angeben, welche dann vonne BindingList gewrappert wird.
Du kannst also von außen auf der InnerList arbeiten, und dann machste

BindingList.ResetBinding();

und alle Bindings werden geupdatet.
Eine solche BindingList würde ich als DataSource der BindingSource verwenden.

Und nicht ständig neue DataSources zuweisen, sondern die eine clearen und neu befüllen oderso.

Also quasi 3 Level von DataSources:
Listbox.DataSource = {BindingSource}
BindingSource.DataSource = {BindingList}
BindingList ist mit dem Konstruktor erstellt, der eine zu wrappernde "InnerList" angibt.
Der NebenThread würde also auf der InnerList arbeiten, und wenner fertig ist, BindingList.ResetBinding() invoken, und gut is.
Evtl. gehts sogar ohne Control._Begin_Invoke, im Dataset geht das jedenfalls.

Der frühe Apfel fängt den Wurm.

I
itstata Themenstarter:in
302 Beiträge seit 2008
vor 15 Jahren

das hört sich ja genial an, werd ich gleich mal probieren.
vielen dank. Die klassen des .net's sind doch unergründlich 😃

nachtrag. das ist ne super klasse wie ich finde. haben eben auf meinem singlecore 10 mio strings eingefügt. das frame war noch relativ gut "ansprechbar". realisiert mit bindingnavigator:


public partial class Form1 : Form
    {
     
        List<String> list;
        BindingList<String> bl;

        public Form1()
        {
            InitializeComponent();
            list = new List<string>();
            bl = new BindingList<string>(list);
            bs.DataSource = bl;
            this.label1.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.bs, "", true));
        }


        private void BindData()
        {
            for (int i = 0; i < 10000000; i++)
            {
                list.Add("Test" + i);
            }
            this.label1.Invoke(new MethodInvoker(SetBS));
        }

        private void SetBS()
        {
            this.progressBar1.Visible = false;
            bl.ResetBindings();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            new Thread(BindData).Start();
        }
    }

besten dank für den tipp.

5.299 Beiträge seit 2008
vor 15 Jahren

Mit ohne Progressbar kannste sogar direkt auf bs.ResetBindings() invoken:


        private void BindData()
        {
            for (int i = 0; i < 10000000; i++)
            {
                list.Add("Test" + i);
            }
            this.BeginInvoke(bs.ResetBindings);
        }

BeginInvoke hat prinzipiell den Vorzug, dasses nicht auf den anderen Thread wartet.
Ist hier zwar ohne Belang, weil dein Thread eh ausläuft, ob nun sofort, oder ob er noch wartet, bis alle Bindings im GuiThread aktualisiert sind ...

Der frühe Apfel fängt den Wurm.