kör en okompilerad asmx. hrmmm.... Nu funkar .net4 på min w2k3 sp2 - maskin. Du använder inte Visual Studio för att köra dina projekt? Tror inte visual studio är problemet. Problemet nu löst (tror jag). Som du kanske märkt är det är en väldigt, väldigt, väldigt dålig idé att lägga Thread.Sleep inuti ett synkroniserat block... Sleep var bara inlagt för attt testa parallelliteten.web.config, okompilerad asmx
skriven i vb.net
behöver göra den flertrådad.
vill använda parallell.for
detta verkar kräva .net4
hur gör jag för att ange att .net4 ska användas?
hittat diverse exempel som säger att man ska lägga in detta i web.config
<system.web>
<compilation targetFramework="4.0" />
</system.web>
C:\temp\abcd.asmx: ASP.NET runtime error: Okänt attribut: targetFramework. Observera att attributnamn är skiftlägeskänsliga.
vill använda
Imports System.Threading
Imports System.Threading.Tasks
vilket verkar kräva .net4
/ Mikael
Sv:web.config, okompilerad asmx
Var fel i referensen till .net4
Åtgärdat.
Nu funkar det så långt.
Orsaken till att jag behövde net4 är att jag vill köra parallell.for .
Jag får inte det att fungera.
om man kör for next skulle det bli liknande detta
function func1() as string
sql = "SELECT wono from....."
Dim dataAdapter As New SqlDataAdapter(sql, connection)
Dim dsx As New DataSet()
dataAdapter.Fill(dsx)
dim r as string=""
For I = 0 To dsx.Tables(0).Rows.Count - 1
r+=func2(dsx.Tables(0).Rows(I).Item("wono"))
next
return r
end function
Den kommer loopa genom 50 poster.
Func2 returnerar en sträng.
Varje func2 tar ca 0,5s.
Dvs denna funktion tar ca 25s.
Jag vill köra dessa anrop till func2 parallellt, och konkatinera deras strängresultat, och sedan returnera den konkatinerade strängen från func1.
Hur???
Sv: web.config, okompilerad asmx
Min asmx fungerar.
Däremot kan jag inte nyttja threading.
När jag lägger in threading-filerna i bin, får jag
Source Error:
Line 109: <add assembly="System.Web.DynamicData, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
Line 110: <add assembly="System.Web.ApplicationServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
Line 111: <add assembly="*" />
Line 112: </assemblies>
Line 113: <buildProviders>
Source File: C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Config\web.config Line: 111
Förklaring?Sv:web.config, okompilerad asmx
Ibland underlättar det ganska mycket ..
//PelleSv: web.config, okompilerad asmx
Jag använder dock det, men kompilerar inte webservicen.
Nu har jag fungerande .net4 mm.
Får inte trådningen att fungera.
Lite exempel:
<WebMethod(Description:="ThreadTest3a2")> _
Function ThreadTest3a2() As String
Dim ret As String = "", i1 As Int64, i2 As Int64, i3 As Int64, i4 As Int64
Dim sync As New Object()
Try
Dim sNames As String() = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"}
i3 = Math.Round(DateTime.Now.TimeOfDay.TotalMilliseconds, 0)
ret = "Start:" & i3 & ";"
Parallel.For(0, sNames.Count, Sub(i)
SyncLock sync
i1 = Math.Round(DateTime.Now.TimeOfDay.TotalMilliseconds, 0)
Thread.Sleep(2000)
i2 = Math.Round(DateTime.Now.TimeOfDay.TotalMilliseconds, 0)
ret += sNames(i) & ":" & i1 & ":" & i2 & ":" & i2 - i1 & ";"
End SyncLock
End Sub)
i4 = Math.Round(DateTime.Now.TimeOfDay.TotalMilliseconds, 0)
ret += "End:" & i4 & ":" & i4 - i3 & ";"
Catch ex As Exception
Return ex.Message
End Try
Return ret
End Function
Detta returnerar
Start:33875903;
A:33875918:33877918:2000;
C:33877918:33879918:2000;
G:33879918:33881918:2000;
E:33881918:33883918:2000;
I:33883918:33885918:2000;
B:33885918:33887918:2000;
D:33887918:33889918:2000;
F:33889918:33891918:2000;
H:33891918:33893918:2000;
J:33893918:33895918:2000;
End:33895918:20015;
Dvs vi kan se att all 10 variablerna körs.
Alla 10 tar exakt 2000 ms (Thread.Sleep(2000)).
Totala tiden är ca 20s.
Det jag vill uppnå är att totala tiden ska vara 2s (2000ms).
Dvs i en optimal värld skulle svaret vara
Start:33875903;
A:33875903:33876103:2000;
C:33875903:33876103:2000;
G:33875903:33876103:2000;
E:33875903:33876103:2000;
I:33875903:33876103:2000;
B:33875903:33876103:2000;
D:33875903:33876103:2000;
F:33875903:33876103:2000;
H:33875903:33876103:2000;
J:33875903:33876103:2000;
End:33876103:2000;
tar jag bort SyncLock blir det detta svar
Start:34753101;
A:34754726:34755101:375;
E:34755101:34755101:0;
D:34755101:34755101:0;
G:34755101:34755101:0;
F:34755101:34755726:625;
H:34755101:34756726:1625;
J:34755101:34757101:2000;
End:34757101:4000;
Dvs flera fel.
Alla 10 svaren kommer inte med.
Totala tiden blir av ngn anledning 4s.
Sleep verkar inte funka.
Orsaken till detta är ju att det skrivs till ret från alla möjliga håll helt utan kontroll.
Jag gillar inte flertrådat, blir bara trassel (beroende på att jag inte får det att fungera).
Men jag har inget val, måste få upp prestandan rejält.
Pelle, jag har fått bra hjälp av dig under snart 15 år, hoppas på det även i detta fall.
Sv:web.config, okompilerad asmx
Orsaken verkar ligga i konkatineringen av strängarna.
Lösningen blev att lägga strängarna, som är svaren på de parallella anropen, i en array.
När den parallella loopen är klar, konkatinerat jag strängarna från arrayen till en total sträng.
Tester kommer .....Sv: web.config, okompilerad asmx
Synkblocket bör vara så litet och kärnfullt som möjligt för att förhindra att trådarna blockeras längre än nödvändigt -- syftet med blocket bör vara att skydda en delad resurs. I detta fall är det variabeln ret som delas mellan trådarna och som behöver skyddas.
i1 och i2 däremot bör *inte* delas mellan trådarna eftersom de bara används internt i den anonyma funktionen.
D.v.s.
Parallel.For(0, sNames.Count, Sub(i)
Dim i1, i2 As Integer ' Varje tråd får en egen i1 och i2
Dim retDelta As String
i1 = Math.Round(DateTime.Now.TimeOfDay.TotalMilliseconds, 0)
Thread.Sleep(2000)
i2 = Math.Round(DateTime.Now.TimeOfDay.TotalMilliseconds, 0)
' Gör så mycket beräkningar som möjligt utanför låset
retDelta = sNames(i) & ":" & i1 & ":" & i2 & ":" & i2 - i1 & ";" & vbNewLine
Console.WriteLine("{0}: {1}", i, Thread.CurrentThread.ManagedThreadId)
SyncLock sync ' Lås bara då det är absolut nödvändigt
ret += retDelta
End SyncLock
End Sub)
Svaret på frågan om varför operationen tar 4 sekunder istället för 2 är lite lurigt. Det beror på den miljö som koden körs på och (i det här fallet) framförallt på hur många kärnor som finns. Baserat på detta kommer scheduleraren som Parallell.For använder kommer fatta ett beslut om hur många trådar som är lämpligt att skapa upp. Om du kollar på Thread.CurrentThread.ManagedThreadId som skrivs ut till konsollen i koden ovan så bör du kunna se ifall en tråd "återanvänds". I mitt fall med 8 kärnor ser det ut så här:
0: 9
1: 10
2: 11
3: 13
4: 14
5: 16
6: 15
7: 17
8: 12
9: 9
D.v.s. Tråd 9 används för både sNames(0) och sNames(9). Därför tar operationen *som helhet* lika lång tid som dessa två gör tillsammans. Eftersom varje iteration tar minst 2000 ms så kommer hela rasket alltså ta minst 2000 + 2000 = 4000 ms.
Sv:web.config, okompilerad asmx
Synclock fungerar inte.
Det medför att stor del av flödet därmed körs seriellt i alla fall.
Jag kör nu på en viruell maskin, med 4 virtuella CPUer/kärnor.
Jag kör 50 parallella trådar.
Varje enskild tråd tar ca 1,0s att köra.
Hela anropet (50 anrop i 50 trådar) tar ca 1,2s.
Dvs garanterat full flertrådning.
Jag märker ingen prestandaförsämring om jag ökar fr 50 till exempelvis 200 trådar.
(anledningen till att jag har just 50, är att mottagande system som tar emot denna XML har 50 trådar)
Enda lösningen jag hittat är att lägga resultatet av varje enskild tråd i en strängarray, och när parallell.for är klar, konkatinera alla strängarna från arryen. Det är nog bl.a. här som mina extra 0,2s ligger i exemplet ovan.