在次线程上为引用类型对象赋值,然后从主线程处理此对象



我正试图在线程一上创建一个类型为MyReferenceTypeObject且值为null的变量,在线程二上使用委托使该线程等于MyReferenceTypeObject的新实例,然后在线程一(在委托回调方法中)访问MySReferenceTypeobject的成员。

我的代码如下:

Module Module1
    Delegate Sub EditReferenceTypePropertyDelegate(ByVal referenceTypeObject As MyReferenceTypeObject, ByVal numberToChangeTo As Integer)
    Sub Main()
        Dim editReferenceDelegate = New EditReferenceTypePropertyDelegate(AddressOf EditReferenceTypeProperty)
        Dim newReferenceTypeObject As MyReferenceTypeObject
        editReferenceDelegate.BeginInvoke(newReferenceTypeObject, 2, AddressOf EditReferenceCallback, newReferenceTypeObject)
        Console.ReadLine()
    End Sub
    Sub EditReferenceTypeProperty(ByVal referenceTypeObject As MyReferenceTypeObject, ByVal numberToChangeTo As Integer)
        referenceTypeObject = New MyReferenceTypeObject()
        referenceTypeObject.i = numberToChangeTo
    End Sub
    Sub EditReferenceCallback(ByVal e As IAsyncResult)
        Dim referenceObject = DirectCast(e.AsyncState, MyReferenceTypeObject)
        Console.WriteLine(referenceObject)
    End Sub
End Module
Class MyReferenceTypeObject
    Public Property i As Integer
End Class

但是,newReferenceTypeObject以null形式进入我的回调方法。我想我理解为什么,但问题是我需要从数据库中提取一些数据,然后将这些数据传递到newReferenceTypeObject的构造函数中,这需要几秒钟的时间,而且我不想在发生这种情况时锁定我的UI。我想在线程一上创建一个类型为MyReferenceTypeObject的字段,在线程二上实例化它(在我提取了数据库的数据以传递到构造函数之后),然后在实例化完成后在线程一中处理对象的成员。

这可能吗?我在Visual Studio 2012上使用VB.Net和.Net 4.0。

如果您想在长时间运行的操作中保持GUI的响应性,我会考虑使用Task<>库(随.NET 4.0一起提供)。下面是一个简单的例子。

Sub Main()
        Dim instantiateTask = New Task(Of MyReferenceTypeObject)(Function()
                                                                     ' Call your database to pull the instantiation data.
                                                                     Return New MyReferenceTypeObject With {.i = 2}
                                                                 End Function)
        instantiateTask.Start() ' Start the task -> invokes a ThreadPool.Thread to do the work.
         instantiateTask.ContinueWith(Sub(x)
                                     Console.WriteLine(x.Result.I)
                                 End Sub, TaskScheduler.FromCurrentSynchronizationContext())
    End Sub

CCD_ 3阻塞GUI线程。但是,您可以使用ContinueWith,它是异步的,因此是非阻塞的。此外,您还需要从GUI线程提供TaskSchedulerTaskScheduler.FromCurrentSynchronizationContext),以防止在您希望从异步方法中更新UI时出现跨线程异常。

最新更新