[VB.NET] Datatable uitlezen & threads

Pagina: 1
Acties:
  • 190 views sinds 30-01-2008
  • Reageer

  • Swerfer
  • Registratie: Mei 2003
  • Laatst online: 26-05 22:09
Ik heb een thread waarin op de volgende manier een datatable wordt uitgelezen:
Visual Basic .NET:
1
2
3
4
5
6
7
Dim ds As DataSet = DataSet1
Dim dt As DataTable = ds.Tables("links")
Dim dr As DataRow
For Each dr In dt.Rows
    ' hier wordt voor elke row een bestand gedowload van internet
    ' wat dus enige tijd kost
Next
Ergens anders in de mainthread wordt op een gegeven moment een row toegevoegd aan de datatable 'links'

Daar onststaat dus ook het probleem. De thread begint te klagen dat de datatable is gewijzigd. De volgende foutmelding krijg ik:

An unhandled exception of type 'System.InvalidOperationException' occurred in mscorlib.dll

Additional information: Collection was modified; enumeration operation may not execute.


Ik dacht dat met
Visual Basic .NET:
1
Dim dt As DataTable = ds.Tables("links")
de datatable dt een nieuwe collectie wordt met een kopie van de table 'links'?

Blijkbaar niet dus! Als er een nieuwe row wordt toegevoegd in de table 'links' in de oorspronkelijke dataset, dan wordt blijkbaar ook de 'kopie' (datatable dt) aangepast...

Is dit op te vangen door op de één of andere manier een echte kopie van de datatable te creeren?

Home Assistant | Unifi | LG 51MR.U44 | Volvo EX30 SMER+ Vapour Grey, trekhaak | SmartEVSE V3 | Cronos Crypto.com


  • SWfreak
  • Registratie: Juni 2001
  • Niet online
Het enige wat ik zo snel kan vinden is de copy() methode van DataTable. Lost dit het probleem op? Anders moet je misschien alle benodigde data zelf even kopieren en zorgen dat er in de tussentijd niet in de DB geschreven wordt...

  • Swerfer
  • Registratie: Mei 2003
  • Laatst online: 26-05 22:09
SWfreak schreef op 30 december 2003 @ 17:41:
Het enige wat ik zo snel kan vinden is de copy() methode van DataTable. Lost dit het probleem op? Anders moet je misschien alle benodigde data zelf even kopieren en zorgen dat er in de tussentijd niet in de DB geschreven wordt...
Bedankt, ik heb het als volgt opgelost:
Visual Basic .NET:
1
2
Dim dt As DataTable = ds.Tables("links")
dt = dt.Copy()

[ Voor 3% gewijzigd door Swerfer op 30-12-2003 17:53 ]

Home Assistant | Unifi | LG 51MR.U44 | Volvo EX30 SMER+ Vapour Grey, trekhaak | SmartEVSE V3 | Cronos Crypto.com


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Dat is overigens OOK een shallow copy.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
EfBe schreef op 30 december 2003 @ 18:51:
Dat is overigens OOK een shallow copy.
Zoals de topic starter het doet is toch geen shallow copy? Dat is gewoon een referentie naar de datatable. Ik zie nergens waar hij een kopie maakt.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • EfBe
  • Registratie: Januari 2000
  • Niet online
In de post boven de mijne:

Dim dt As DataTable = ds.Tables("links")
dt = dt.Copy()

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Verwijderd

Het is toch ook mogelijk om het LOCK key-woord te gebruiken? :X

edit:

Ownee, cristal lult slap. Want, dan is ie gelocked en wacht thread net zo lang tot hij niet kan copie'ren (niet gelocked is) dus. Ik heb niets gepost :+

[ Voor 58% gewijzigd door Verwijderd op 30-12-2003 20:35 ]


Verwijderd

Ik zou gewoon een global table aanhouden...

in de mainthread deze locken en dan een row toevoegen en weer unlocken...

in de download-thread de table ook locken, row eruit trekken, unlocken en downloaden...

  • Swerfer
  • Registratie: Mei 2003
  • Laatst online: 26-05 22:09
Visual Basic .NET:
1
2
Dim dt As DataTable = ds.Tables("links")
dt = dt.Copy()
Wat is hier dan mis mee? Het heeft mijn probleem opgelost...

Aangezien mijn tabellen toch nooit meer dan 500 rows kunnen bevatten, waar per row maximaal 10kb aan data inzit, lijkt het me ook geen performance of geheugen probleem. Vooral als je bedenkt dat het downloaden van 1 bestand waarschijnlijk meer tijd kost dan het kopieren van 1 tabel...

Home Assistant | Unifi | LG 51MR.U44 | Volvo EX30 SMER+ Vapour Grey, trekhaak | SmartEVSE V3 | Cronos Crypto.com


Verwijderd

Swerfer schreef op 30 december 2003 @ 21:01:
Visual Basic .NET:
1
2
Dim dt As DataTable = ds.Tables("links")
dt = dt.Copy()
Wat is hier dan mis mee? Het heeft mijn probleem opgelost...

Aangezien mijn tabellen toch nooit meer dan 500 rows kunnen bevatten, waar per row maximaal 10kb aan data inzit, lijkt het me ook geen performance of geheugen probleem. Vooral als je bedenkt dat het downloaden van 1 bestand waarschijnlijk meer tijd kost dan het kopieren van 1 tabel...
Als je een kopie maakt van die datatable dan zie je toch niet meer de toevoegingen welke de MainThread doet? Plus als je het doet zoals mijn vorige post dan kan een aantal download threads start en zo meerdere bestanden gelijktijdig downloaden....

  • whoami
  • Registratie: December 2000
  • Laatst online: 15:14
Verwijderd schreef op 30 december 2003 @ 21:17:
[...]

Als je een kopie maakt van die datatable dan zie je toch niet meer de toevoegingen welke de MainThread doet? Plus als je het doet zoals mijn vorige post dan kan een aantal download threads start en zo meerdere bestanden gelijktijdig downloaden....
Een DataRow houdt een status bij (modified, inserted, deleted), en houdt ook z'n huidige en vorige (originele) waarden bij.
Zolang de de AcceptChanges() method niet hebt gebruikt, gaan de toegevoegde rows niet als 'unmodified' oid gemarkeerd worden.

https://fgheysels.github.io/


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Swerfer schreef op 30 december 2003 @ 21:01:
Visual Basic .NET:
1
2
Dim dt As DataTable = ds.Tables("links")
dt = dt.Copy()
Wat is hier dan mis mee? Het heeft mijn probleem opgelost...
Er is niets mis mee, je moet alleen niet zeggen dat het een copy van je data is want dat is het niet, je hebt alleen een nieuwe datatable gecreert die wijst naar dezelfde data.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:14
EfBe schreef op 30 december 2003 @ 21:21:
[...]
Er is niets mis mee, je moet alleen niet zeggen dat het een copy van je data is want dat is het niet, je hebt alleen een nieuwe datatable gecreert die wijst naar dezelfde data.
Hoe bedoel je? Bedoel je nu dat z'n 2 datasets naar hetzelfde geheugenadres wijzen?
Nee toch?
Want dan zou deze code, als output
Aantal rows in ds1: 1
moeten hebben;

code:
1
2
3
4
5
6
7
8
9
10
11
12
DataSet ds = new DataSet();
ds.Tables.Add(new DataTable());
ds.Tables[0].Columns.Add("naam");
            
DataSet ds1 = ds.Copy();
            
DataRow dr = ds.Tables[0].NewRow();
dr["naam"] = "blaat";
ds.Tables[0].Rows.Add(dr);
            
        
MessageBox.Show("Aantal rows in ds1: " + ds1.Tables[0].Rows.Count.ToString());

https://fgheysels.github.io/


  • Swerfer
  • Registratie: Mei 2003
  • Laatst online: 26-05 22:09
Verwijderd schreef op 30 december 2003 @ 21:17:
[...]


Als je een kopie maakt van die datatable dan zie je toch niet meer de toevoegingen welke de MainThread doet? Plus als je het doet zoals mijn vorige post dan kan een aantal download threads start en zo meerdere bestanden gelijktijdig downloaden....
Als ik toevoegingen in de mainthread doe, dan gaat het ten alle tijden om lokale bestanden. Het is dus niet nodig dat de downloadthread die toevoegingen ook gaat doorlopen.
EfBe schreef op 30 december 2003 @ 21:21:
[...]

Er is niets mis mee, je moet alleen niet zeggen dat het een copy van je data is want dat is het niet, je hebt alleen een nieuwe datatable gecreert die wijst naar dezelfde data.
Nog beter dus, dan is de 'gekopieerde' datatable dus nog klein ook.

Maar wat als ik een row vanuit de mainthread wis? Dan kan de 'gekopieerde' datatable dus geen (juiste) gegevens meer ophalen...

Ik denk dat ik toch een andere methode moet gaan toepassen.

Het is de bedoeling dat de downloadthread op de achtergrond thumbnails download. De links haalt hij uit een datatable Thumbnails genaamd. Als hij een thumbnail gedownload heeft, dan wordt die thumbnail als image opgeslagen in dezelfde tabel. Wordt er in de tussentijd door de mainthread een row gewist, dan zit de downloadthread dus met een probleem. Hoe kan ik dat het beste oplossen?

Home Assistant | Unifi | LG 51MR.U44 | Volvo EX30 SMER+ Vapour Grey, trekhaak | SmartEVSE V3 | Cronos Crypto.com


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
EfBe schreef op 30 december 2003 @ 20:15:
In de post boven de mijne:

Dim dt As DataTable = ds.Tables("links")
dt = dt.Copy()
Oke als je het zo bedoelt wel. Ik dacht dat je bedoelde dat hij in zijn eerste post ook een shallow copy maakte. ( Komt vooral door het woordje ook. ).
Hoe bedoel je? Bedoel je nu dat z'n 2 datasets naar hetzelfde geheugenadres wijzen?
Nee toch?
Want dan zou deze code, als output
Ik denk dat hij bedoelt dat de data hetzelfde is. Dus je hebt wel een referentie naar een andere table maar de referenties van de table naar de data zijn hetzelfde. Ik weet dit trouwens niet zeker want heb nog nooit geprobeerd een DataTable te kopieren.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Verwijderd

Ik zou toch nog steeds het oplossen met locking...

In MainThread:
---------------
1. Lock Datatable
2. add link
3. unlock Datatable


In Download Thread
------------------
1. lock Datatable
2. maak een dataview waarin alleen de rijen komen waar thumbnail voor gedownload moet worden (en welke nog niet al gedownload worden, voor het geval je meerdere download threads wil gebruiken)
3. Sla ID en link van eerst row in dataview op, en unlock Datatable
(is er geen row beschikbaar in de dataview dan thread even laten slapen en terug naar stap 1)
4. download bestand
5. lock Datatable
6. Zoek rij op in datatable met het onder 3 opgeslagen ID
7. Als deze rij nog bestaat (dus mainthread heeft rij niet gedelete), update thumbnail data
8. unlock datatable
9. begin weer met stap 1

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Ik denk dat hij bedoelt dat de data hetzelfde is. Dus je hebt wel een referentie naar een andere table maar de referenties van de table naar de data zijn hetzelfde. Ik weet dit trouwens niet zeker want heb nog nooit geprobeerd een DataTable te kopieren.
Als je met reflector kijkt dan copieert hij rows middels CopyRow (internal functie) die creeert gewoon references naar dezelfde columns.

[ Voor 50% gewijzigd door EfBe op 31-12-2003 00:03 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
EfBe schreef op 31 december 2003 @ 00:02:
[...]

Als je met reflector kijkt dan copieert hij rows middels CopyRow (internal functie) die creeert gewoon references naar dezelfde columns.
Oke dan klopt mijn verhaaltje nog steeds een klein beetje. Je hebt dus alleen een nieuwe DataTable maar met dezelfde DataRows.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Swerfer
  • Registratie: Mei 2003
  • Laatst online: 26-05 22:09
Verwijderd schreef op 31 december 2003 @ 00:00:
Ik zou toch nog steeds het oplossen met locking...

In MainThread:
---------------
1. Lock Datatable
2. add link
3. unlock Datatable


In Download Thread
------------------
1. lock Datatable
2. maak een dataview waarin alleen de rijen komen waar thumbnail voor gedownload moet worden (en welke nog niet al gedownload worden, voor het geval je meerdere download threads wil gebruiken)
3. Sla ID en link van eerst row in dataview op, en unlock Datatable
(is er geen row beschikbaar in de dataview dan thread even laten slapen en terug naar stap 1)
4. download bestand
5. lock Datatable
6. Zoek rij op in datatable met het onder 3 opgeslagen ID
7. Als deze rij nog bestaat (dus mainthread heeft rij niet gedelete), update thumbnail data
8. unlock datatable
9. begin weer met stap 1
Dit heb ik nu ongeveer zo gedaan, behalve dan het locken van de datatable. Ik kan nergens enige informatie vinden over het locken van datatables in .net framework.
code:
1
2
3
4
5
6
7
8
9
1  Maak nieuwe datatable met ID's en Link's uit originele datatable
2  Download thumbnail
3  ***Hier zou de originele datatable gelockt moeten worden
4  Kijk of row nog bestaat in originele datatable
5a Zo ja, insert de thumbnail in die row
5b Zo nee, doe niets
6  ***Hier zou de originele datatable unlocked moeten worden
7  Ga verder met stap 2 als nog niet alle thumbnails zijn gedownload
8  Einde thread

Home Assistant | Unifi | LG 51MR.U44 | Volvo EX30 SMER+ Vapour Grey, trekhaak | SmartEVSE V3 | Cronos Crypto.com


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:14
Swerfer schreef op 31 december 2003 @ 11:09:
[...]

Dit heb ik nu ongeveer zo gedaan, behalve dan het locken van de datatable. Ik kan nergens enige informatie vinden over het locken van datatables in .net framework.
[/code]
Zoek eens op het lock keyword.

code:
1
2
3
lock(blaat)
{
}

https://fgheysels.github.io/


  • Swerfer
  • Registratie: Mei 2003
  • Laatst online: 26-05 22:09
whoami schreef op 31 december 2003 @ 12:39:
[...]


Zoek eens op het lock keyword.

code:
1
2
3
lock(blaat)
{
}
Nope, alleen lock in combinatie met files gevonden niks over datatables of datasets locken...

Home Assistant | Unifi | LG 51MR.U44 | Volvo EX30 SMER+ Vapour Grey, trekhaak | SmartEVSE V3 | Cronos Crypto.com


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:14
Hmmm, C# kent dit:
The lock keyword marks a statement block as a critical section by obtaining the mutual-exclusion lock for a given object, executing a statement, and then releasing the lock. This statement takes the following form:
code:
1
lock(expression) statement_block


where:

expression
Specifies the object that you want to lock on. expression must be a reference type.
Typically, expression will either be this, if you want to protect an instance variable, or typeof(class), if you want to protect a static variable (or if the critical section occurs in a static method in the given class).

statement_block
The statements of the critical section.
C# programmer's reference

VB.NET zal -hopelijk- toch ook wel iets dergelijks kennen ?

[ Voor 3% gewijzigd door whoami op 31-12-2003 13:22 ]

https://fgheysels.github.io/


  • Swerfer
  • Registratie: Mei 2003
  • Laatst online: 26-05 22:09
whoami schreef op 31 december 2003 @ 13:22:
Hmmm, C# kent dit:

[...]

C# programmer's reference

VB.NET zal -hopelijk- toch ook wel iets dergelijks kennen ?
Gevonden:
Visual Basic .NET:
1
2
3
SyncLock expression
    ...[ block ]
End SyncLock
Bedankt...

Home Assistant | Unifi | LG 51MR.U44 | Volvo EX30 SMER+ Vapour Grey, trekhaak | SmartEVSE V3 | Cronos Crypto.com

Pagina: 1