[Alg/vb.net] Late Binding of een nettere manier?

Pagina: 1
Acties:

  • bramseltje
  • Registratie: September 2001
  • Laatst online: 23-05 10:13
Voor een projectje (nou ja, stageopdracht) ben ik druk bezig met het proberen te schrijven van een applicatie in VB.NET. Alles werkt (bijna) precies zoals ik het bedoeld heb, dus daar is niks mis mee.

Omdat ik niet zo netjes programmeer (tja, Electro, en geen IT'er :D) wil ik niet het risico lopen dat m'n programma niet meer reageert omdat er iets mis gaat bij het bevragen van de database ofzo. Dus ik werk met verschillende threads. Ook dat werkt naar behoren, en m'n programma blijft ondertussen ook fijn doorwerken. Allemaal leuk en aardig.

Maar nu heb ik in de klasse die als thread wordt uitgevoerd ook een ResultObject zitten. Hierin komen (in dit geval) de resultaten van de uit te voeren query. Omdat dit van alles kan zijn, van een TextBox tot een StringCollection heb ik dit op moeten lossen door middel van Late Binding.

Hierbij zijn dus de methoden en eigenschappen van het object pas bekend bij uitvoering van de code. Omdat hier nog wel wat lastigheidjes aan zitten, zoals het risico dat je een niet bestaande methode aanroept, is het misschien niet zo'n nette manier. Van de andere kant, zolang ik de enige ben die aan het programma werk weet ik (meestal nog wel tenminste :X) welke objecten ik in de klasse kan stoppen.

Mijn vraag is nu dus eigenlijk een beetje: Zijn er mooiere (en eenvoudiger) oplossingen voor dit probleem?

Zoals bijvoorbeeld het schrijven van een (overloaded) methode voor alle mogelijke objecten. Alleen is dit erg veel werk. Maar vanuit een veiligheids of stabiliteits oogpunt is dit misschien wel een betere oplossing.

Je zou natuurlijk ook kunnen zeggen dat je maar een type object aan de klasse kunt verbinden, maar hierdoor wordt je oplossing een stuk minder flexibel.

Laat hier je ideeen maar los, en ik hoop dat er vruchtbaar gediscussierd kan worden...

Voorbeeldje Late Binding:

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Dim a As String
Dim s As String

s.Text = "nieuw"
a.Text = "oud"

TextWissel(a, s.Text)
'Als het goed gaat is a.Text nu "nieuw" en s.Text "oud"

Sub TextWissel(byref InObject As Object, ByRef InString As String)

    Dim t As String

    t = Object.Text
    'Mogelijk error, als object geen Text property heeft, anders gaat het wel goed

    Object.Text = InString
    'Ook dit gaat alleen goed als je het juiste object gebruikt

    InString = t

    t = Nothing

End Sub

  • bramseltje
  • Registratie: September 2001
  • Laatst online: 23-05 10:13
Jammer dat er niemand lijkt te zijn die hetzelfde probleem tegen komt...

Heeft dat misschien iets te maken met het feit dat ik niet eerst m'n programma ontworpen heb? :+

Maar zijn er geen algemene ontwerp regels om te voorkomen dat je late binding nodig hebt? Ook als je je klassen zo algemeen mogelijk wil houden? (ivm hergebruik)

Verwijderd

Je kan in vb.net in ieder geval checken van welk type het object is:
bvb:
code:
1
if typeof object is textbox then

Maar ik vraag mij eigenlijk af waarom jij object gaat wegstoppen in een database?

  • whoami
  • Registratie: December 2000
  • Laatst online: 15:14
Heb je geen uniforme interface die alle objecten delen, of kan je geen uniforme interface maken voor al je objecten?

https://fgheysels.github.io/


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 13:28

gorgi_19

Kruimeltjes zijn weer op :9

whoami schreef op 24 december 2003 @ 00:08:
Heb je geen uniforme interface die alle objecten delen, of kan je geen uniforme interface maken voor al je objecten?
Lees ik hier een Adapter-pattern in?

* gorgi_19 is het GoF-boek weer aan het bestuderen... :)
Omdat dit van alles kan zijn, van een TextBox tot een StringCollection heb ik dit op moeten lossen door middel van Late Binding
Dit laatste snap ik trouwens niet helemaal; waarom zou je een textbox willen opslaan in de database? Een textbox, label, etc. kan je toch meer zien als een 'presentatievorm' van de data (en heeft je DL compleet geen weet van)

[ Voor 38% gewijzigd door gorgi_19 op 24-12-2003 01:43 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:14
gorgi_19 schreef op 24 december 2003 @ 01:36:
[...]

Lees ik hier een Adapter-pattern in?

* gorgi_19 is het GoF-boek weer aan het bestuderen... :)
Zoiets ja. ;)

https://fgheysels.github.io/


  • bramseltje
  • Registratie: September 2001
  • Laatst online: 23-05 10:13
Ik stop geen opjecten in m'n database, ik vul ze vanuit m'n database... :Y)

edit:

[quote=bramseltje]
Omdat DIT vanalles kan zijn
[/quote]
Waarbij DIT dus op het ResultObject sloeg, en niet op het resultaat van de query ;)


wat er gebeurt is het volgende:
In m'n programma heb ik een object, waar de resultaten (of het resultaat, bij een SUM ofzo) van de query in terecht moet komen. Omdat ik een deadlock wil voorkomen, voer ik die query in een aparte thread uit.

Die aparte thread is in VB.NET gewoon een klasse, waarvan je een methode als thread start. Aan deze klasse geef ik dan het resultaat object mee, waarbij dit dus kan verschillen. Als ik een lijst met onderdelen terugkrijg, kunnen die best in een ListBox, maar een Sum heeft niet zoveel zin in een ListBox, dus dat wordt een label of editbox.

Wat ik nu heb is dus eigenlijk een algemene database querier, die een aantal objecten moet kunnen accepteren. (Nou ja, moet, wil het graag algemeen houden...)

@Whoami:
dat van die interfaces snap ik niet echt, ben geen IT-er, en heb nooit iets met design-patterns te maken gehad. Zou je 't mij, noob :+, ff uit kunnen leggen? Hoeft niet te lang hoor...

[ Voor 11% gewijzigd door bramseltje op 24-12-2003 12:58 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:14
Ok, je haalt dus enkel gegevens op uit een DB, en die gegevens wil je tonen op een TextBox, ListBox, ......

Waarom laat je die method niet gewoon de gegevens returnen, en dan kan je in je programma die gegevens gebruiken om je listbox/textbox, whatever mee op te vullen.

https://fgheysels.github.io/


  • bramseltje
  • Registratie: September 2001
  • Laatst online: 23-05 10:13
whoami schreef op 24 december 2003 @ 12:56:
Ok, je haalt dus enkel gegevens op uit een DB, en die gegevens wil je tonen op een TextBox, ListBox, ......

Waarom laat je die method niet gewoon de gegevens returnen, en dan kan je in je programma die gegevens gebruiken om je listbox/textbox, whatever mee op te vullen.
In principe doe ik dit al.

De "structuur" :X is nu als volgt:
code:
1
2
3
4
5
6
7
8
9
10
11
Hoofdprogramma:
    Thread klasse
    klasse.Resultaatobject = object
    thread.run

Thread:
    Result = query
    Raiseevent (result, resultobject)

Handler:
    resultobject = result


Waarbij het in de EventHandler toevoegen van de gegevens aan het object dus aan de hand van het type moet gebeuren. Als je een ListBox.Text probeert te veranderen, zul je een error krijgen, dus dat moet je wel in de gaten houden.

Ik heb het op deze manier omdat ik anders een globale variabele ofzo moet gaan maken, waar ik m'n resultaatobject in stop, zodat ik daar vanuit de eventhandler bij kan.

als ik de reference meegeef aan de thread, kan de thread deze aan de eventhandler meegeven, en ben ik van dat probleem af. alleen ben ik nu dus nog steeds niet van te voren op de hoogte van het type.

Lijkt dit een beetje op de algemene interface naar de database toe? Want je zult in die interface toch ook de verschillende typen objecten moeten onderkennen, en afhandelen op de goede manier.

Ik doe het nu zo:
code:
1
2
3
4
5
select case ResultObject.GetType.ToString
    case "textbox" : code
    case "listbox" : code
    enz.
end select

Da's ongeveer wat hierboven al gezegd werd, maar dan zonder het type expliciet als object aan te geven (ResultObject.GetType = TextBox). Stiekem hoop ik dat dit minder geheugen kost ;) Hoeft er geen object aangemaakt te worden om te kunnen vergelijken...

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 27-05 23:27

Creepy

Tactical Espionage Splatterer

Waarom niet een type ResultObject dat je gebruikt om mee te geven als reference, en dan een instantie van een (subclass van) ResultObject gebruiken. Nadat die instantie gevult is vul je a.d.v. dat object je GUI objecten.

En als je resultaat alleen maar een string is, waarom dan niet zoals whoami zegt, rechtstreeks een string teruggeven als resultaat van de functie?

[ Voor 34% gewijzigd door Creepy op 24-12-2003 13:24 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • bramseltje
  • Registratie: September 2001
  • Laatst online: 23-05 10:13
Het resultaat van de query is altijd een DataReader, soortement van tabel dus. Het kan natuurlijk zijn dat er maar een record in zit, maar het blijft een reader. en die komt dus ook terug van uit de methode

De klasse voor de thread ziet er zo uit:
Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Public Class DataCommandExecute

    Public strCommand As String
    Public objConnection As Data.OleDb.OleDbConnection
    Public objResultObject As Object
    Public strColumn As String

    Public Event DataCommandExecute_Done(ByVal drResult As _
                    OleDb.OleDbDataReader, ByVal objResultObject As Object, _
                    ByVal strColumn As String)

Public Sub ExecuteCommand()
    Try
        Dim aCommand As OleDb.OleDbCommand = New _
                      OleDb.OleDbCommand(strCommand, objConnection)

        aCommand.CommandType = CommandType.Text
        aCommand.CommandText = strCommand

        objConnection.Open()

        drResult = aCommand.ExecuteReader()

        RaiseEvent DataCommandExecute_Done(drResult, objResultObject, strColumn)
        aCommand.Dispose()
        drResult.Close()
    Catch ex As Exception
         'error handling
    Finally
      objConnection.Close
    End Try
End Sub

End Class


Vanuit het hoofdprogramma geef ik de publics een waarde. Zoals je ziet worden het ResultObject en strColumn (de kolom vd database) alleen maar doorgegeven, en niet gebruikt in de methode zelf.

In de EventHandler (die bij de hoofdthread hoort, en niet bij de thread) gebruik ik die dan weer wel, om daarmee het resultaatobject te kunnen vullen. En dat doe ik dan op de manier zoals ik hierboven meldde, met het uitlezen van het type van het object en aan de hand daarvan de goede methodes te gebruiken.

Om even naar de vraag uit m'n startpost te gaan...
Dit blijkt voor mij te voldoen, maar ik vroeg me af of er misschien een eenvoudige, nettere manier is.

  • whoami
  • Registratie: December 2000
  • Laatst online: 15:14
Bramseltje schreef op 24 december 2003 @ 13:41:
Het resultaat van de query is altijd een DataReader, soortement van tabel dus. Het kan natuurlijk zijn dat er maar een record in zit, maar het blijft een reader. en die komt dus ook terug van uit de methode
Een datareader is geen tabel, maar een readonly fast forward recordset.
Als je iets zoals een tabel wilt, kijk dan eens naar een DataTable.

https://fgheysels.github.io/


  • bramseltje
  • Registratie: September 2001
  • Laatst online: 23-05 10:13
Creepy schreef op 24 december 2003 @ 13:22:
Waarom niet een type ResultObject dat je gebruikt om mee te geven als reference, en dan een instantie van een (subclass van) ResultObject gebruiken. Nadat die instantie gevult is vul je a.d.v. dat object je GUI objecten.

...
Dat zou kunnen, maar dan moet ik nog steeds een manier bedenken om van het type ResultObject terug te gaan naar een Label of een ListBox of een StringCollection. Waarbij ik in wezen dus weer hetzelfde probleem heb. Maak ik een .toString functie voor het ResultObject (hoe moet dat dan met een gewone SELECT query???) of moet ik een methode maken die een object als ByRef parameter heeft, en daar dan het resultaat aan toekent? Zit je weer met het probleem dat je niet van te voren weet wat voor Object je krijgt.

Ga ik dan overloaded functies schrijven, of doe ik het met Late Binding... :Y)

Zie je het probleem?

Nou ja goed, ik ben ook maar een Electro man, dus vergeef me mijn botte Informatica wijsheden, maar probeer er gewoon het beste van te maken ;)

In ieder geval bedankt voor de replies tot nu toe, van zulke wijze mannen en jongens als jullie _/-\o_ :+

[ Voor 1% gewijzigd door whoami op 24-12-2003 13:50 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:14
Maar jij weet toch altijd welke query je verstuurd?

Waarom maak je dan geen ander type method voor bepaalde types queries? Zoals je bv in .NET al hebt: ExecuteScalar(), .....

Of, kan je aan je delegate geen method meegeven die jouw specifieke control gaat gaan vullen?

https://fgheysels.github.io/


  • bramseltje
  • Registratie: September 2001
  • Laatst online: 23-05 10:13
whoami schreef op 24 december 2003 @ 13:52:
Maar jij weet toch altijd welke query je verstuurd?

Waarom maak je dan geen ander type method voor bepaalde types queries? Zoals je bv in .NET al hebt: ExecuteScalar(), .....

Of, kan je aan je delegate geen method meegeven die jouw specifieke control gaat gaan vullen?
Nou, niet precies, ik gebruik deze klasse meerdere keren. Om een lijst met componenten te maken, om een totaal prijs uit te rekenen, en nog een paar keer. Dus de query is variabel.

ExecuteScalar() zou inderdaar kunnen als ik altijd een SUM bereken, maar ja, da's dus niet het geval. (help: ExecuteScaler returns first row of first column, every other is ignored)

En delegate? Bedoel je aan de methode binnen de thread?
whoami schreef op 24 december 2003 @ 13:45:
[...]

Een datareader is geen tabel, maar een readonly fast forward recordset.
Als je iets zoals een tabel wilt, kijk dan eens naar een DataTable.
Ja, dat bedoelde ik ;) Maar je kunt geen DataTable (direct) vanuit een DataCommand vullen. Resulteert altijd in een DataReader, dus vandaar... Maar dat gedeelte op zich werkt prima. (En een recordset is toch ook een soort tabel, Excel is dat toch ook? :+:D Tabel is hier een 2d set waarden O-))

Maar zoals het er nu op lijkt heb ik intuitief de makkelijkste oplossing gekozen (nou ja, afgezien van dat threaded verhaal dan, maar stel in VB.Net gelukkig ook niet zoveel voor ;))

Ik kan me ook niet voorstellen dat er hier behoefte is aan de complete code... De file waar het hier om gaat is maar 3800 regeltjes ofzo, dus weet niet of dat in een post past ;)

[ Voor 2% gewijzigd door bramseltje op 24-12-2003 14:04 . Reden: ff iets bij gezet ;) ]


Verwijderd

Ik snap eerlijk gezegd nog steeds niet goed waarom je een object meegeeft aan je functie ... Wat bevat dit object juist ? de datareader ?
Of is dit een generieke functie waar je 2 strings wil wisselen ? van textboxa naar textboxb en van tabela naar labelb etc ? dan zou ik voor iedere soort een andere functie maken, of idd gaan overloaden, altijd zo simpel mogelijke code proberen schrijven, dan heb je het minste kans op problemen :)

  • whoami
  • Registratie: December 2000
  • Laatst online: 15:14
Bramseltje schreef op 24 december 2003 @ 14:02:
[...]


Nou, niet precies, ik gebruik deze klasse meerdere keren. Om een lijst met componenten te maken, om een totaal prijs uit te rekenen, en nog een paar keer. Dus de query is variabel.
Je kan toch een delegate toevoegen aan die klasse, bv:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public delegate void DoWithResults(object sender);

class DataCommandExecute
{

    ..... 
    public delegate DoWithResults    FillAnObjectOrSo;
    ...
}

// gebruik van DataCommandExecute:

DataCommandExecute dc = new DataCommandExecute();
dc.strCommand = "SELECT * FROM personen";
dc.FillAnObjectOrSo += new DoWithResults(FillPersonenListBox);
dc.Execute();


In de execute method ga je bv een DataTable gaan opvullen, en ga je de delegate gaan uitvoeren:
code:
1
2
3
4
5
6
7
8
9
10
void Execute()
{

    MyDataAdapter.Fill (MyDataTable);

    if( FillAnObjectOrSo != null )
    {
           FillAnObjectOrSo(this);
    }
}


En de FillPersonenListBox method (die een member method is van je form bv) ziet er dan bv zo uit:
code:
1
2
3
4
5
6
void FillPersonenListBox(object sender )
{

    PersonenListBox.DataSource = ((DataCommandExecute)sender).MyDataTable;

}
Ja, dat bedoelde ik ;) Maar je kunt geen DataTable (direct) vanuit een DataCommand vullen.
Nee, maar daarvoor bestaat er een data-adapter.

https://fgheysels.github.io/


  • bramseltje
  • Registratie: September 2001
  • Laatst online: 23-05 10:13
Okee, ik heb nu naar aanleiding van whoami's post en deze tutorial het volgende gebrouwen. Met delegates dus:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As _
                                              System.EventArgs) Handles Button1.Click
        Dim a As New ExecuteCommand
        a.sCommandText = "SELECT * FROM [stuklijst algemeen]"
        a.sDataBaseFile = sPathBin & "\db1.mdb"

        StartHere(a)
    End Sub
'------------------------------------------------------------------------------------

    Private Sub StartHere(ByRef d As ExecuteCommand)
        d.WhoToNotify(New ExecuteCommand.Finished(AddressOf comFinished))
        d.runCommand()
    End Sub
'-------------------------------------------------------------------------------------

    Public Sub comFinished(ByVal drResult As OleDb.OleDbDataReader)
        MsgBox("er is iets gebeurd")

        If drResult.HasRows And drResult.Read Then
            MsgBox("Rijen!!!" & vbNewLine & drResult.GetValue(0))
        End If
    End Sub


De klasse is nu dit geworden:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Public Class ExecuteCommand
    Public Delegate Sub Finished(ByVal drResultSet As OleDb.OleDbDataReader)

    Public sDataBaseFile As String
    Public sCommandText As String

    Private Notifier As Finished
    Private _drResultSet As OleDb.OleDbDataReader

    Public Sub WhoToNotify(ByVal val As Finished)
        Notifier = val
    End Sub

'--------------------------------------------------------------------------------
    Public Sub runCommand()
        Dim sConnStr = "Provider=""Microsoft.Jet.OLEDB.4.0"";data source=""" & _
                                                             sDataBaseFile & """"

        Dim oleDbCon As New OleDb.OleDbConnection(sConnStr)

        oleDbCon.Open()

        Dim cCommand As New OleDb.OleDbCommand(sCommandText, oleDbCon)

        cCommand.CommandType = CommandType.Text

        Try
            _drResultSet = cCommand.ExecuteReader
            If Not Notifier Is Nothing Then
                Notifier.Invoke(_drResultSet)
            End If
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
        
    End Sub

End Class


Maar nu heb ik nog steeds het probleem dat ik in de functie die de delegate aanroept, comFinished dus, niet weet waar het resultaat naar toe moet. Dan zou ik dus in de Delegate een extra parameter moeten meegeven, die naar heb object verwijst (ByRef, zoals een pointer in c++) waarmee in dan in de comFinished functie verder kan werken.

Ben ik dan niet precies op het zelfde punt als met de gewone events? Dat ik eerst de bestemming aan de klasse meegeef, en die dan daaruit weer terug krijg in de afhandeling?

* Bram is confused...

  • bramseltje
  • Registratie: September 2001
  • Laatst online: 23-05 10:13
Er is niemand die mij kan vertellen wat ik hier nu precies mee opgeschoten ben? Nadat ik de Delagates heb gebruikt ben ik uiteindelijk nog op hetzelfde punt beland.

Het enige is dat ik in principe dezelfde functie kan gebruiken voor verschillende threads, terwijl ik voor elke aparte thread een eigen event_handler moet bouwen. Klopt dat?

Hmm, toch maar ff verder zoeken...

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 15:57
je kan comFinished toch ook de waarde laten retourneren, of zie ik dat nou mis?

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Bramseltje schreef op 22 december 2003 @ 11:14:
Voor een projectje (nou ja, stageopdracht) ben ik druk bezig met het proberen te schrijven van een applicatie in VB.NET. Alles werkt (bijna) precies zoals ik het bedoeld heb, dus daar is niks mis mee.
Er is een hoop mis mee, anders vroeg je hier je vraag niet.
Omdat ik niet zo netjes programmeer (tja, Electro, en geen IT'er :D) wil ik niet het risico lopen dat m'n programma niet meer reageert omdat er iets mis gaat bij het bevragen van de database ofzo. Dus ik werk met verschillende threads. Ook dat werkt naar behoren, en m'n programma blijft ondertussen ook fijn doorwerken. Allemaal leuk en aardig.
Ik begrijp dit niet. Je moet je programma opdelen in blokken die verschillende taken uitvoeren. Je hebt het, zoals ik het nu bekijk, als 1 grote kluwen gebouwd: van top tot bodem is het multi-threaded? Als je je applicatie responsive wilt houden ten tijde van het uitvoeren van een actie, gebruik je twee threads in de GUI: de main thread die de GUI controlleert (en doorwerkt dus en taken dispatched naar een queue waar nieuwe taken worden gestart) en een thread die de taak uitvoering controlleert, dwz, de actie start mbv andere delen van je code, bv database georienteerde code of een serie classes die werken op de database. Deze 'workerthread' start dus die code en gaat wachten op resultaat van de code die wordt aangeroepen. Als dat binnenkomt komt dat dus als resultaat in het queue item dat ervoor gezorgt heeft dat de taak werd gestart. De main thread moet nu worden ingelicht dat een taak klaar is.

Echter dit is zelden nodig. De gebruiker gaat echt geen 20 taken opstarten die allemaal 3 seconden duren en dan de eis stellen dat alles door moet blijven werken. Je hebt het zeer complex gemaakt wat helemaal niet had gehoeven.
Maar nu heb ik in de klasse die als thread wordt uitgevoerd ook een ResultObject zitten. Hierin komen (in dit geval) de resultaten van de uit te voeren query. Omdat dit van alles kan zijn, van een TextBox tot een StringCollection heb ik dit op moeten lossen door middel van Late Binding.
Leg me eens uit waarom in vredesnaam GUI objects in een resultobject staan? Je hebt resultaten, data dus, en die hebben een type. Dat type is bekend bij de dataproducer. Dat type vermeld je eventueel in resultobject maar je kunt dat ook achterhalen door GetType(resultobject.Value) oid en dan een select case. Verder ga je in je GUI de data interpreteren en in gui elements stoppen. Dat is niet de taak van de dataproducer, maar van de GUI. De GUI is verder gewoon single threaded, die interpreteert de taakresultaten en toont een gui element (formpje oid). Het is heel simpel: User start actie door button click -> button event handler start taak door method call. Taak eindigt en resultaat wordt geinterpreteert door diezelfde method en resultaat wordt verwerkt -> user ziet resultaat. Vindt er ergens iets plaats wat niet had gemoeten, gooi je een exception, die komt terecht in de taak start method, die toont de exception of handelt hem af en taak afgelopen. Hoezo multi-threaded?

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


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Bramseltje schreef op 24 december 2003 @ 12:52:
wat er gebeurt is het volgende:
In m'n programma heb ik een object, waar de resultaten (of het resultaat, bij een SUM ofzo) van de query in terecht moet komen. Omdat ik een deadlock wil voorkomen, voer ik die query in een aparte thread uit.
Die voorkom je daar niet door, je vergroot de kans op deadlocks juist. Om deadlocks te voorkomen moet je weten waardoor ze ontstaan: reader blocked by writer en writer blocked by exclusive lock by reader. Dat laatste komt standaard niet voor, het eerste in sqlserver wel, wanneer je bv een transaction uitvoert, iets insert in een table (of delete) en daarna IN die transaction een select doet op dezelfde table met een where clause waarin een field zit zonder index. Dit resulteert in een tablescan en die blocked op de row die is geinsert/gedelete. Omdat die lock niet wordt opgeheven voordat de transaction is gecommit/rolledback en dat niet gebeurt voordat de select is afgelopen heb je een deadlock.

Hoe voorkom je dus deadlocks? Door niet te lezen tijdens een transaction die schrijft EN waarbij de leesactie nodig is voor de transactie. Doe je dat niet, heb je geen deadlocks, simpel. Multiple threads kunnen zorgen voor een deadlock wanneer je meerdere shared resources gebruikt (bv een connection) en threads op elkaar gaan wachten. Single threaded acties hebben dat niet.

Multi-threading is complexe materie en veelal alleen nodig wanneer je worker/main threads acties wilt opstarten (bv port-listener main thread die connection threads spawned) echter jouw app lijkt me daar absoluut niet geschikt voor. DB acties kunnen prima in single threaded code.

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

Pagina: 1