Lock up in the line filestream.readstring

schimanski

Well-Known Member
Licensed User
Longtime User
Hello!

It's a problem, that I want to place in a new thread, because up to the present, there is no solution.

B4X:
if client.dataavailable=true then
   gps.gpsstream(filestream.readsting)
end if

My network-application locks up in the line filestream.readsting, when the server stops sending data. The reason for the problem is:

Client.dataavailable realize, that there is data in the stream. Filestream.readsting reads the protocoll from start-bit to the finish-bit. When the server stops sending, the finish-bit (LAST_ACK) don't arrive, so the client locks up in the line filestream.readsting. Client.dataavailable only notes, that there is data in the stream, but not, that it is a noncomplete TCP-protocol without the finish-bit.

I think, that there are three attempts at a solution:

1. client.dataavailable realize, that there is no complete TCP-protocoll in the stream and gets false,
2. filestream.readstring doesn't need a finish-bit of the TCP-protocoll,
3. filestream.readstring contains a timeout-function.

The door-lib contains such a timeout-function, but it only runs on the desktop, not on the device.

Did anybody know, how I can prevent a lock up in the filestream.readstring? Perhaps there are some other solutions....
:sign0085:
 

Cableguy

Expert
Licensed User
Longtime User
Wrong Sub-forum...
This belongs in Q&A......

A "stupid"(?) sugestion would be to enable a timer everitime a bit arrives, and use it as a timeout...If at the second or third tick cout no bit were received then Cole the dataStream Reader...
 

schimanski

Well-Known Member
Licensed User
Longtime User
Sorry!

I think, that I have missunderstood the last post from Erel to the old thread:

Another approach you could try is to move the network code to a different
thread with agraham's Threads library.

Can you tell me the right place?


Thanks and I will try your solution....
 

Cableguy

Expert
Licensed User
Longtime User
Erel is the only one who can now move this thread....
Any way, don't take it as ofensive...Many of us have made this mistake, that can sometimes render our post Not to be read or simply looked over...

Also, I think Erel was talking about the threadind Dll released by Agraham...
Check my dll listing, you'll find there a link to it...
 

schimanski

Well-Known Member
Licensed User
Longtime User
It's a good idea, but how can I deliver the data from the network-thread to my application?:confused:
 

schimanski

Well-Known Member
Licensed User
Longtime User
Hello together!

I think, that the threading.dll is, what I'am looking for. I have read all the documentation, but I don't know, what to do. My english isn't good enough... Is it possible, to give me a little bit help with the following code?:sign0148:

The Sub-Thread should run seperate and give the data in NMEA to the Main-Thread, so that the Main-Thread does't lock up, when the Sub-Thread does:

B4X:
'Read NMEA from Server'
'Main-Thread'
Sub Globals
   NMEA=""
End Sub

Sub App_Start   
   client.New1
   filestream.New1(client.GetStream,False)
   Client.Connect ("217.91.....",?????)   
   timer1.Enabled=True
End Sub

Sub Timer1_Tick
   gps.GPSStream(NMEA)
End Sub

Sub GPS_GPSDecoded
   ...
   ....
   ...
End Sub
'--------------------------'
'Sub-Thread' 
Sub Timer2_Tick   
   If client.DataAvailable=True Then
      NMEA=filestream.ReadString
   Else
      label1.Text="no data"
   End If
End Sub
 

agraham

Expert
Licensed User
Longtime User
B4X:
'Sub-Thread' 
Sub Timer2_Tick   
   If client.DataAvailable=True Then
      NMEA=filestream.ReadString
   Else
      label1.Text="no data"
   End If
End Sub
1) You can't run a Timer on a separate thread, they always run on the main thread. Use Sleep in a loop instead

2) You can't directly access GUI elements in a separate thread or you will get an error or a crash. You must use a thread event instead.

You need something along these lines - note that I haven't run this code.
B4X:
dim Ctl
Dim Data

Thread.Start(ThreadSub)


' this is very simplified, you really need a Select ... Case to decide what to do
' that switches on a global variable
Sub Thread_ThreadEvent
    Control(Ctl).Text = Data
End Sub

'------------------------

Sub ThreadSub
    Do While Something
        Sleep(1000)
        If client.DataAvailable=True Then
            NMEA=filestream.ReadString
        Else
            Ctl = "Label1"
            Data = "no data"
            Thread.FireThreadEvent ' Event runs on the main thread
        End If
    Loop
End Sub
 

schimanski

Well-Known Member
Licensed User
Longtime User
Only one help!!

Hello! I have write the short test-application below, but I always get the message, that 'start' in the legacy-mode in not available. I have set optimising on true and false an I have compiled the application, but always the same message. What is wrong?:confused:

B4X:
Sub Globals
    Optimising = True 
   Dim Ctl
   Dim Data
End Sub

Sub App_Start
   Form1.Show
   Thread.New1( B4PObject ( 1 ))
   client.New1
   Client.Connect ("217.91......",.....)
   filestream.New1(client.GetStream,False)
   Label3.Text="Server connected"
   Thread.Start(ThreadSub)
End Sub

Sub Thread_ThreadEvent
    Control(Ctl).Text = Data
End Sub

Sub CheckBox1_Click
   If checkbox1.Checked=True Then
      Thread_ThreadEvent
   End If
End Sub

Sub ThreadSub
    Do While checkbox1.Checked=True
        Sleep(1000)
        If client.DataAvailable=True Then
            Data=filestream.ReadString
        Else
            Ctl = "Label12"
            Data = "no data"
            Thread.FireThreadEvent ' Event runs on the main thread
        End If
    Loop
End Sub
 

agraham

Expert
Licensed User
Longtime User
I have compiled the application, but always the same message.
It looks as though you have not optimised compiled your app, that message means that the library thinks it is running in legacy mode where threading is not possible.

B4X:
Sub Globals
    [COLOR="Red"]Optimising = True[/COLOR] ' this is unnecessary as you don't use it
   Dim Ctl
   Dim Data
[COLOR="SeaGreen"]   Dim CheckedFlag[/COLOR]
[COLOR="seagreen"]   CheckedFlag = checkbox1.Checked[/COLOR]
End Sub

Sub App_Start
   Form1.Show
   Thread.New1( B4PObject ( 1 ))
   client.New1
   Client.Connect ("217.91......",.....)
   filestream.New1(client.GetStream,False)
   Label3.Text="Server connected"
   Thread.Start(ThreadSub)
End Sub

Sub Thread_ThreadEvent
    Control(Ctl).Text = Data
End Sub

Sub CheckBox1_Click
   [COLOR="SeaGreen"]CheckedFlag = checkbox1.Checked[/COLOR]
   If checkbox1.Checked=True Then
      Thread_ThreadEvent
   End If
End Sub

Sub ThreadSub
    ' Do While [COLOR="red"]checkbox1.Checked[/COLOR]=True ' this is part of the GUI, to be safe you should not do this
 Do While [COLOR="SeaGreen"]CheckedFlag  [/COLOR]' this is how to do it
       Sleep(1000)
        If client.DataAvailable=True Then
            Data=filestream.ReadString
        Else
            Ctl = "Label12"
            Data = "no data"
            Thread.FireThreadEvent ' Event runs on the main thread
        End If
    Loop
End Sub
[/QUOTE]
 

schimanski

Well-Known Member
Licensed User
Longtime User
Thanks, for the code. But when I start the code I get the following messages:

HTML:
Library running in legacy mode
Start, RunLock and Join are unavailable

Start
Not available in legacy mode

I have activated File/Compile/Optimized Compilation. Is there anything else, which must be activated?

I also have compiled it on the device, but the same messages. Every other libraries, which need the optimized compilation and .NET Compact Framework 2.0 runs.

Agraham's testapplications of the Threading-Lib have also the messages above...

:confused:
 

agraham

Expert
Licensed User
Longtime User
IAgraham's testapplications of the Threading-Lib have also the messages above...
Are you using the latest Threading library version 1.3? Are you using Basic4ppc version 6.50?

To make sure there is no error in the archive I have just downloaded Threading1.3.zip, unzipped it and optimised compiled ThreadTest for both Desktop and Device. Both work fine for me.

For some reason the library thinks it is running in legacy mode. If you can't find what is wrong then post both a desktop optimised compiled exe and the source code and I'll see what it does for me.

EDIT:- You are not expecting it to run in the IDE are you? For threading to work the optimised compiled exe must be run directly, either by clicking it in File Manager (Desktop and Device) or by having Basic4ppc run it (Desktop only) after compilation by selecting File->Compile->Run After Compiling.
 
Last edited:

schimanski

Well-Known Member
Licensed User
Longtime User
Hello agraham!

I use the last Threading.dll (Version 1.0.3179.22342) and also the basic4pcc 6.50 for desktop and device.

I have compiled it optimized for device and desktop, but on both I get a message from windows, that the application must be closed, because there is a big mistake occurred.
Then I start it under the IDE on the desktop with 'optimized compilation' and 'run after compile'. Result: 'Start etc. not available in legacy mode'.

I post the source, the desktop and the device.exe. :sign0085:
 
Last edited:

agraham

Expert
Licensed User
Longtime User
the application must be closed, because there is a big mistake occurred.
I should have noticed it before. This is the big mistake "Thread.Start(ThreadSub)". It should be

Thread.Start("ThreadSub")
or
Thread.Start("Main.ThreadSub")
if ThreadSub is in the Main module

or

Thread.Start("ModuleName.ThreadSub")
if ThreadSub is in another module

I guess I ought to add a check in the Threading library that a Sub exists before trying to run it.

Then I start it under the IDE on the desktop with 'optimized compilation' and 'run after compile'. Result: 'Start etc. not available in legacy mode'.
Running in the IDE is always legacy mode. 'optimized compilation' and 'run after compile' do nothing in the IDE, they only affect the compiled exe produced by File->Compile->SomeTarget
 

schimanski

Well-Known Member
Licensed User
Longtime User
Threading.dll for network-application....

:sign0060:

The Threading.dll was the solution of the problem.

I have encapsulate the sub, which reads from the network-stream, in a separate thread-sub and it works perfect. I think, there are many advantages towards a timeout-function:

First, the application don't blocks, when it is waiting for the timeout.
Second: Because "filestream.readsting" is a blocking-function, the application will respond with a short delay. When the reading-sub is a separate thread, the main application runs without any delays.
And last but not least: it runs on desktop and device....

I have test a lot, until I have a functioning testapplication. So, if there is someone who has the same problem, I post my little testapplication. Perhaps there is someone who ca use it. It's an application, which reads NMEA-data from a network-stream.

Thanks for the many help.....
 

Attachments

  • ThreadingTest.sbp
    3.5 KB · Views: 169
Last edited:
Top