Странное поведение ...

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

Klinifini
Новичок
Новичок
 
Сообщения: 29
Зарегистрирован: 23.08.2006 (Ср) 17:37

Странное поведение ...

Сообщение Klinifini » 31.08.2006 (Чт) 18:13

Не могу понять в чем причина ошибки.. Вот код:
Код: Выделить всё
Do
            lenght = client_networkStream.Read(bytes, 0, bytes.Length)
            ReDim Preserve bdata(bdata.GetUpperBound(0) + lenght)
            'System.Threading.Thread.Sleep(100)
            [Array].Copy(bytes, 0, bdata, bdata.GetUpperBound(0) - lenght, lenght)
        Loop While client_networkStream.DataAvailable

Странное поведение в том, что принимается только кусок файла, но если раскомментировать строку System.Threading.Thread.Sleep(100), то файл принимается полностью до последнего байта! В чем причина?

Чудик
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 639
Зарегистрирован: 06.07.2004 (Вт) 12:18
Откуда: г. Егорьевск

Сообщение Чудик » 01.09.2006 (Пт) 21:36

По всему могу предположить, что не успев выполнить до конца (завершить)
Код: Выделить всё
lenght = client_networkStream.Read(bytes, 0, bytes.Length)
            ReDim Preserve bdata(bdata.GetUpperBound(0) + lenght)

приложение приступает к выполнению очередной строки кода. При включении задержки ты даешь возможность завершить операцию. У меня было что-то похожее, когда я формировал в БД таблицу и потом связывал ее с Gridом. Таблица не успевала заполниться необходимой информацией, когда начиналось связывание. В результате Grid отображал не все положенные данные. Пришлось код делить на две части и привязывать каждую к отдельному событию, давая, тем самым, сначала полностью сформироваться таблице, а затем выполнить привязку.
В связи с чем такое явление имеет место не имею представление.
Век живи - век учись!
www.detal-plast.narod.ru

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 02.09.2006 (Сб) 12:48

попробуй так:

Код: Выделить всё
Try
    Do
         lenght = client_networkStream.Read(bytes, 0, bytes.Length)
         ReDim Preserve bdata(bdata.GetUpperBound(0) + lenght)
         [Array].Copy(bytes, 0, bdata, bdata.GetUpperBound(0) - lenght, lenght)
     Loop
Catch

End Try
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Klinifini
Новичок
Новичок
 
Сообщения: 29
Зарегистрирован: 23.08.2006 (Ср) 17:37

Сообщение Klinifini » 02.09.2006 (Сб) 13:36

Чудик, скорее всего ты прав. Только вот как мне с этим бороться?
Nord777, твой вариант работает, но проблема в том, что исключение не создается и из цикла выход не происходит :cry: .. Т.е. тот же ризультат что и от :
Код: Выделить всё
Do
    lenght = client_networkStream.Read(bytes, 0, bytes.Length)
    ReDim Preserve bdata(bdata.GetUpperBound(0) + lenght)
    [Array].Copy(bytes, 0, bdata, bdata.GetUpperBound(0) - lenght, lenght)
Loop

:cry:

Чудик
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 639
Зарегистрирован: 06.07.2004 (Вт) 12:18
Откуда: г. Егорьевск

Сообщение Чудик » 02.09.2006 (Сб) 13:45

Как с этим бороться, надеюсь, подскажут наши соратники по форуму, так как у меня нет идей по этому поводу (у меня не такие глубокие познания в VB насколько это необходимо).
Век живи - век учись!
www.detal-plast.narod.ru

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 02.09.2006 (Сб) 16:44

А так?

Код: Выделить всё
  Do
      lenght = client_networkStream.Read(bytes, 0, bytes.Length)
      If lenght = 0 Then Exit Do
      ReDim Preserve bdata(bdata.GetUpperBound(0) + lenght)
      [Array].Copy(bytes, 0, bdata, bdata.GetUpperBound(0) - lenght, lenght)
  Loop While client_networkStream.DataAvailable
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Klinifini
Новичок
Новичок
 
Сообщения: 29
Зарегистрирован: 23.08.2006 (Ср) 17:37

Сообщение Klinifini » 02.09.2006 (Сб) 17:25

Nord777, ты наверно имел ввиду Loop без While. Но lenght не будет равно нулю, потому что на строке lenght = client_networkStream.Read(bytes, 0, bytes.Length) программа ожидает данные и поток блокируется :cry:
Но ты мне дал идею:
If lenght < bytes.Length Then System.Threading.Thread.Sleep(100)
Это тоже неправильно, но лучше, чем было :)

Продолждаю ждать идей.

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 02.09.2006 (Сб) 23:35

рассажи чего ты ждешь от этого кода?
если просто скачать файл:
Код: Выделить всё
Public Function DownloadData(ByVal address As String) As Byte()
     Member of: System.Net.WebClient
Summary:
Downloads the resource with the specified URI as a System.Byte array.

Parameters:
address: The URI from which to download data.

Return Values:
A System.Byte array containing the downloaded resource.


Откопал свой старый проект от VS2003 (Чат).
Код: Выделить всё
    Public Sub ThreadSub()
        Dim data(1000) As Byte
        Dim i As Integer
        Dim MessageIn As String = ""

        Do
            Do Until NWS1.DataAvailable
                'крутить цикл пока не появятся данные
                Threading.Thread.Sleep(250)
            Loop
            'читаем данные
            i = NWS1.Read(data, 0, 1000)
            MessageIn = System.Text.Encoding.Default.GetString(data).Substring(0, i)
            TextBoxIn.Text &= MessageIn & vbCrLf
        Loop
    End Sub 


если ничего не подойдет - то рассказывай все нюансы твоей задачи.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Klinifini
Новичок
Новичок
 
Сообщения: 29
Зарегистрирован: 23.08.2006 (Ср) 17:37

Сообщение Klinifini » 03.09.2006 (Вс) 13:08

Все, вроде разобрался... Вроде пашет.
Nord777, я делаю HTTP прокси. Спасибо, Do Until NWS1.DataAvailable - интересно, использовал, работает )
И я выхожу на финальную прямую, как вывести обмен данными в отдельный поток. Код:
Код: Выделить всё
Private Sub wait()
        Try
            Log("Слушаем Порт")
            listener.Start()
            Do
                HTTPProvider.Flush()
                Log("Ожидание клиента")
                Do
                    If listener.Pending Then
                        server_tcpClient = listener.AcceptTcpClient()
                        Exit Do
                    End If
                    Threading.Thread.Sleep(100)
                Loop
                Log("- Клиент Подключен")
                Log("-- Прием запроса от клиента")
                Log("----- Принято: 0 байт")

                server_networkStream = server_tcpClient.GetStream
                Do Until server_networkStream.DataAvailable
                    Threading.Thread.Sleep(100)
                Loop

                Do
                    lenght = server_networkStream.Read(bytes, 0, bytes.Length)
                    If lenght < bytes.Length Then System.Threading.Thread.Sleep(100)
                    HTTPProvider.AddBinaryData(bytes, lenght)
                    LastItem("----- Принято: " & HTTPProvider.BinaryData.Length & " байт")
                Loop While server_networkStream.DataAvailable

                Dim Host As String = HTTPProvider.GetHost

                Log("-- Подключение к серверу " & Host)
                Dim client_tcpClient As New Net.Sockets.TcpClient
                client_tcpClient.Connect(Host, 80)

                Log("-- Передача запроса серверу")

                client_networkStream = client_tcpClient.GetStream()
                client_networkStream.Write(HTTPProvider.BinaryData, 0, HTTPProvider.BinaryData.Length)
                HTTPProvider.Flush()
                Log("-- Прием ответа от сервера")
                Log("----- Принято: 0 байт")

                Do Until client_networkStream.DataAvailable
                    Threading.Thread.Sleep(100)
                Loop

                Do
                    lenght = client_networkStream.Read(bytes, 0, bytes.Length)
                    If lenght < bytes.Length Then System.Threading.Thread.Sleep(100)
                    HTTPProvider.AddBinaryData(bytes, lenght)
                    LastItem("----- Принято: " & HTTPProvider.BinaryData.Length & " байт")
                Loop While client_networkStream.DataAvailable

                Log("-- Передача ответа сервера клиенту")
                server_networkStream.Write(HTTPProvider.BinaryData, 0, HTTPProvider.BinaryData.Length)

                server_networkStream.Close()
                client_networkStream.Close()
                server_tcpClient.Close()
                client_tcpClient.Close()
                Log("- Сессия завершена")

            Loop

        Catch e As ThreadAbortException
            listener.Stop()
        End Try
    End Sub


Причем чтобы для каждого потока создавался свой элемент HTTPProvider.. И уж больно не хочется выносить метод в отдельный класс, можно как-нибудь без этого обойтись ? (Потому-что в ходе работы вызывается методы Log и LastItem, а они в свою очередь пишут инфу в ListBox на форме, а если в другом классе, то я не знаю как это сделать)
Заранее хочу всех поблагодарить за помощь Nord777, Чудик, tyomitch, GSerg, !Viper!, Sebas и keks-n. Спасибо! :lol:

Klinifini
Новичок
Новичок
 
Сообщения: 29
Зарегистрирован: 23.08.2006 (Ср) 17:37

Сообщение Klinifini » 03.09.2006 (Вс) 13:10

Это сообщение написано через мой прокси!!! Ураа!

Klinifini
Новичок
Новичок
 
Сообщения: 29
Зарегистрирован: 23.08.2006 (Ср) 17:37

Сообщение Klinifini » 03.09.2006 (Вс) 13:28

Так, кое-как многопотоковость сделал, но большие файлы качаются не полностью, поэтому надо всетаки делать проверку Content-Lenght =(

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 04.09.2006 (Пн) 9:53

Скинь мне пожалуйста свой проект. Я в свое время тоже писал прокси и мне стало очень интересно нарвешься ли ты на те же грабли что и я (на досуге сравню проекты).
а заодно пронумеруй те вопросы что у тебя остались.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 04.09.2006 (Пн) 10:18

Небольшой примерчик поможет разобраться с многопотчностью:
Код: Выделить всё
Imports System.Threading

Public Class Form1
    Private demoThread As Thread = Nothing
    'Обьявляем делегата на процедуру с одним параметром
    Delegate Sub SetTextCallback(ByVal [text] As String)

    Private Sub setTextSafeBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles setTextSafeBtn.Click
        Me.demoThread = New Thread(AddressOf Me.ThreadProcSafe)
        Me.demoThread.Start()
    End Sub

    Private Sub ThreadProcSafe()
            'создадим экземпляр делегата на процедуру которая принимает один аргумент типа String
            'И назначим этому делегату адрес процедуры 'ST'
            Dim d As New SetTextCallback(AddressOf ST)

            For x As Integer = 1000 To 0 Step -1
            'Вызовем этого делегата в том потоке, в котором
            'создались все элементы управления
            'Me - Form1
            Me.Invoke(d, New Object() {x.ToString})
        Next
    End Sub

    Private Sub ST(ByVal MyText As String)
        TextBox1.Text = MyText
    End Sub

End Class
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 19

    TopList