none
background workers (or something similar)

    Question

  • Hi :)

    what i am working on is a file converter. ATM the entire process happens for when i click on a button. This freezes the program and results in it not responding. The file conversion takes for ever but does work. Problem is my estimated time and progressbar don't work.

    Can anyone think of a solution to this so it appears to run smoothly.

    of course i don't expect you to write th code for me, but some hints and a url would be much appreciated. I've never done anything like this before. But i will have soon :)

    Thanks
    Friday, June 13, 2008 8:40 PM

Answers

  • So the rule is you can't make a call to a form or control that was created by another Thread unless you use a Delegate. Most of the time it is best to save whatever info in a private variable or a property that is delcared at the class level. Not being privi to your code I can guess something like this

    Class WhatEverYourClassIsCalled  
        Private stringArray() As String 
     
        Private Sub ConvertFile()  
            Dim c(num) As Byte 
            Dim iPosition As Integer = 0  
            For Each s As String In stringArray  
                Dim bitem As Byte = Convert.ToByte(s, 16)  
                c(iPosition) = bitem  
                iPosition += 1  
            Next 
     
            My.Computer.FileSystem.WriteAllBytes("xyz.file", c, False)  
        End Sub 
    End Class 

    Fill your stringArray prior to starting your thread and it should work
    • Marked as answer by Semicolin Tuesday, June 17, 2008 6:27 PM
    Monday, June 16, 2008 4:18 PM
  • A quick and dirty fix:

    Control.CheckForIllegalCrossThreadCalls = False

    Brandon Legault
    • Marked as answer by Semicolin Tuesday, June 17, 2008 6:27 PM
    Monday, June 16, 2008 4:32 PM
  •  To use the Listview from a new tread you would have to create a Delegate and Invoke it like this:

        Private Sub ConvertFile()  
            Dim stringArray(num) As String 
            Do Until num2 = num  
     
                stringArray(num2) = ListViewGetItemText(num2)  
                num2 = num2 + 1  
            Loop 
     
            Dim c(num) As Byte 
            Dim iPosition As Integer = 0  
            For Each s As String In stringArray  
                Dim bitem As Byte = Convert.ToByte(s, 16)  
                c(iPosition) = bitem  
                iPosition += 1  
            Next 
     
            My.Computer.FileSystem.WriteAllBytes("xyz.file", c, False)  
        End Sub 
     
     
        Private Delegate Function delListViewGetItemText(ByVal Index As IntegerAs String 
     
        Private Function ListViewGetItemText(ByVal Index As IntegerAs String 
            Dim RetText As String 
     
            If ListView1.InvokeRequired Then 
                Dim MyDelegate As New delListViewGetItemText(AddressOf ListViewGetItemText)  
     
                RetText = ListView1.Invoke(MyDelegate, New Object() {Index})  
            Else 
                RetText = ListView1.Items(Index).Text  
            End If 
     
            Return RetText  
        End Function 

    but like I said earlier it would be much easier to fill the StringArray values prior to spinning off the new tread
    • Marked as answer by Semicolin Tuesday, June 17, 2008 6:27 PM
    Monday, June 16, 2008 7:44 PM

All replies

  • This should get you started

    Public Class frmTreadTest  
        Private thrdConvertWorker As System.Threading.Thread  
     
        Private Sub frmThreadTest_Load(ByVal sender As ObjectByVal e As System.EventArgs) Handles frmThreadTest.Load  
            thrdConvertWorker = New System.Threading.Thread(AddressOf ConvertFile)  
     
            thrdConvertWorker.IsBackground = True 
     
            thrdConvertWorker.Start()  
        End Sub 
     
        Private Sub ConvertFile()  
            'Code here to convert File  
        End Sub 
    End Class 

    use a timer to check to see if thrdConvertWorker IsNot Nothing and if thrdConvertWorker.IsAlive = true when they are not you can stop your progress bar. if you set your progress bar to Marquee you don't have to worry about calcing percent complete

    Help here:
    http://msdn.microsoft.com/en-us/library/system.threading.thread_members.aspx
    • Proposed as answer by TechNoHick Friday, June 13, 2008 10:18 PM
    Friday, June 13, 2008 10:17 PM
  • It seems to be working however i have a problem with threading

    it errors me with

    'Cross-thread operation not valid: Control 'ListView1' accessed from a thread other than the thread it was created on.'

    I did some research on google and msdn help. It all seemed over complicated to me and i got no answer.

    I did find one for C# annoyingly where they just disabled the control that caused this 'safe threadin' check.

    Is there a similar equivilant for vb?
    Sunday, June 15, 2008 9:04 PM
  • here's my converter thing incase it's something i've done wrong :)

        Private Sub ConvertFile() 
            Dim stringArray(num) As String 
            Do Until num2 = num 
     
                stringArray(num2) = Me.ListView1.Items.Item(num2).Text 
                num2 = num2 + 1 
            Loop 
     
            Dim c(num) As Byte 
            Dim iPosition As Integer = 0 
            For Each s As String In stringArray 
                Dim bitem As Byte = Convert.ToByte(s, 16) 
                c(iPosition) = bitem 
                iPosition += 1 
            Next 
     
            My.Computer.FileSystem.WriteAllBytes("xyz.file", c, False
        End Sub 

    Sunday, June 15, 2008 9:06 PM
  • So the rule is you can't make a call to a form or control that was created by another Thread unless you use a Delegate. Most of the time it is best to save whatever info in a private variable or a property that is delcared at the class level. Not being privi to your code I can guess something like this

    Class WhatEverYourClassIsCalled  
        Private stringArray() As String 
     
        Private Sub ConvertFile()  
            Dim c(num) As Byte 
            Dim iPosition As Integer = 0  
            For Each s As String In stringArray  
                Dim bitem As Byte = Convert.ToByte(s, 16)  
                c(iPosition) = bitem  
                iPosition += 1  
            Next 
     
            My.Computer.FileSystem.WriteAllBytes("xyz.file", c, False)  
        End Sub 
    End Class 

    Fill your stringArray prior to starting your thread and it should work
    • Marked as answer by Semicolin Tuesday, June 17, 2008 6:27 PM
    Monday, June 16, 2008 4:18 PM
  • A quick and dirty fix:

    Control.CheckForIllegalCrossThreadCalls = False

    Brandon Legault
    • Marked as answer by Semicolin Tuesday, June 17, 2008 6:27 PM
    Monday, June 16, 2008 4:32 PM
  • Brandon Legault said:

    A quick and dirty fix:

    Control.CheckForIllegalCrossThreadCalls = False


    Brandon Legault

    Haha. very poor solution.


    Can you use a BackgroundWorker? or does it have to be a Thread?

    You can use delegates to access the GUI controls from the thread, but they still need to be invoked correctly.








    Monday, June 16, 2008 7:03 PM
  •  To use the Listview from a new tread you would have to create a Delegate and Invoke it like this:

        Private Sub ConvertFile()  
            Dim stringArray(num) As String 
            Do Until num2 = num  
     
                stringArray(num2) = ListViewGetItemText(num2)  
                num2 = num2 + 1  
            Loop 
     
            Dim c(num) As Byte 
            Dim iPosition As Integer = 0  
            For Each s As String In stringArray  
                Dim bitem As Byte = Convert.ToByte(s, 16)  
                c(iPosition) = bitem  
                iPosition += 1  
            Next 
     
            My.Computer.FileSystem.WriteAllBytes("xyz.file", c, False)  
        End Sub 
     
     
        Private Delegate Function delListViewGetItemText(ByVal Index As IntegerAs String 
     
        Private Function ListViewGetItemText(ByVal Index As IntegerAs String 
            Dim RetText As String 
     
            If ListView1.InvokeRequired Then 
                Dim MyDelegate As New delListViewGetItemText(AddressOf ListViewGetItemText)  
     
                RetText = ListView1.Invoke(MyDelegate, New Object() {Index})  
            Else 
                RetText = ListView1.Items(Index).Text  
            End If 
     
            Return RetText  
        End Function 

    but like I said earlier it would be much easier to fill the StringArray values prior to spinning off the new tread
    • Marked as answer by Semicolin Tuesday, June 17, 2008 6:27 PM
    Monday, June 16, 2008 7:44 PM
  • Ok, thanks for that.

    Thanks for explaining it to me. I know what i gotta do and hopefully it'll work happily

    i'll let you know

    thanks
    Tuesday, June 17, 2008 5:14 PM
  • Thanks, you're fantastic.

    :)
    Tuesday, June 17, 2008 6:49 PM