创建新线程

时间:2016-01-02 02:28:16

标签: .net vb.net multithreading thread-safety

为了简单起见,我试图将一个Class作为参数传递给另一个由不同线程拥有的方法。这是我的代码的简化:

Friend Sub SplitFile(ByVal fileSplitterSettings As FileSplitterSettingsObject)
        Dim _threadSplitFile As New System.Threading.Thread(Sub() Thread_SplitFile_Start(fileSplitterSettings))          
        _threadSplitFile.Start()
End Sub

ThreadFile()正在调用SplitFile(),它创建线程2,传入一个在线程1中实例化的对象,作为将在线程2的上下文中运行的方法的参数。

但是,每当我尝试在线程2下运行的Thread_SplitFile_Start方法中访问 fileSplitterSettingsObject 时,我都会收到一条错误,指出其他线程拥有它。

我知道 Dispatcher.Invoke()以及如何使用它来运行,读取和更改其他线程的方法和对象,但我不确定如何在此处实现它。我可以在Thread_SplitFile_Start中的Thread 2的上下文中创建该类的新实例,并对Thread_SplitFile_Start中的每个属性使用Dispatcher.Invoke(),以便将来自Thread 1的上下文中的fileSplitterSettings的值复制到线程2的上下文中的一个新实例,但这似乎有点矫枉过正,我正在寻找一个更简单的替代方案。

如果需要任何其他信息,我很乐意提供。

非常感谢任何帮助或建议!

编辑:

由于传递原始类型(如整数,字符串等)工作正常,我认为传入一个结构类型会起作用,但这似乎也不起作用。

编辑:

这是我正在使用的这门课程。这是我创建的,所以我需要改变所需的任何更改:

Namespace Classes

Friend NotInheritable Class FileSplitterSettingsObject

地区"枚举"

    Friend Enum FileSavingMode
        ModeTogether = 0
        ModeSeparate = 1
    End Enum

结束地区

地区"属性"

    Private _propertyDeleteOriginalFile As Boolean = False
    Private _propertyUseCustomSuffixes As Boolean = False
    Private _propertyFilenameSuffixes As List(Of ListBoxItem)
    Private _propertySavingMode As FileSavingMode = Nothing

    Friend Property DeleteOriginalFile As Boolean
        Get
            Return _propertyDeleteOriginalFile
        End Get
        Set(value As Boolean)
            _propertyDeleteOriginalFile = value
        End Set
    End Property

    Friend Property UseCustomSuffixes As Boolean
        Get
            Return _propertyUseCustomSuffixes
        End Get
        Set(value As Boolean)
            _propertyUseCustomSuffixes = value
        End Set
    End Property

    Friend Property FileNameSuffixes As List(Of ListBoxItem)
        Get
            Return _propertyFilenameSuffixes
        End Get
        Set(value As List(Of ListBoxItem))
            _propertyFilenameSuffixes = value
        End Set
    End Property

    Friend Property SavingMode As FileSavingMode
        Get
            Return _propertySavingMode
        End Get
        Set(value As FileSavingMode)
            _propertySavingMode = value
        End Set
    End Property

结束地区

End Class

结束命名空间

我很抱歉没有提前澄清这一点,但我可以访问"大多数"线程2中的这些属性。我唯一无法访问的是 FileNameSuffixes ,它在线程1中设置如下:

For i As Integer = 0 To lbSuffixes.Items.Count - 1
        lbSuffixesItemsList.Add(New ListBoxItem With {
                                                         .Content = CType(lbSuffixes.Items(i), ListBoxItem).Content
                                                     })
Next

我认为它与在线程1中实例化ListBoxItems有关,这就是线程2无法访问它们的原因。基本上,我需要将这些项目传递给线程2,因此我可以访问它们的属性。我知道我可以创建一个String类型的列表,它可能会工作,但是很高兴知道我将来要做的事情是否可以完成(例如,对于同时设置了多个属性的对象,不想基于原始类型创建一堆自定义属性,只是为了传递信息)

2 个答案:

答案 0 :(得分:0)

这可能太简单了(我没有你的对象可以测试),但我认为。使用你的代码进行调用看起来像这样:

Dispatcher.Invoke(Sub()
    Dim _threadSplitFile As New System.Threading.Thread(Sub() Thread_SplitFile_Start(fileSplitterSettings))          
        _threadSplitFile.Start()
End Sub)

或者这个:

Dim _threadSplitFile As New System.Threading.Thread(Sub() Thread_SplitFile_Start(fileSplitterSettings))          
Dispatcher.Invoke(Sub()
        _threadSplitFile.Start()
End Sub)

...取决于您收到错误的位置。

但是 - 您正在创建2个线程,这些线程将等待主线程执行(因为fileSplitterSettings不是线程安全的)。如果我是你,我会考虑重新设计。也许:

  1. 在线程安全的类中传递您需要的设置(例如 - 您创建的类)。即使这只是fileSplitterSettings

  2. 之上的一个外观
  3. 在此主题中创建一个fileSplitterSettings对象,

  4. 在同一个帖子中执行.Start。

  5. 然后 - 你得到多线程,不需要捣乱调度员。再一次,可能过于简单化了,我不知道你的环境/限制。希望至少能为你提供一些游戏!

答案 1 :(得分:0)

在与@Brian Saunders合作之后,我确定最好只使用通用字符串数组来传递这个麻烦的属性。