父集合的参考影响分配的集合 [英] Reference of parent collection affecting the assigned collection

查看:88
本文介绍了父集合的参考影响分配的集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任务: 我有一个要求(用户能连续挽救一个接一个,而无需等待),所以我选择多线程和我即将完成与队列的概念。但我有一个场景卡住了。

关于code任务: 有众多的收藏品和对象的应用程序,我创建了一个队列类,并创建了一个单独的集合和对象在和所有那些被分配到队列类的对象。每当用户保存所有这些集合和对象被填充并分配给队列集合和对象,并添加在队列中的变化,所以背景工人开出集合和对象,并执行处理。这样做是为了确保保存的值是正确的,因为有持续保存。

方案: 应用程序具有在其中用户选择一个行,并使用一个唯一的ID,从它的值被收集和结合到形式中装入一个网格。因此,用户将更新的值,然后点击保存。然后,他点击了下一行,一旦装载值,他再次做了修改和save.This是哪里出现问题。

既然我已经分配的所有的previous收集到队列集合,当用户做出保存更改并点击和他去下一行,并点击是,收集present已经在应用越来越复位(因为在收集被复位的每一行选择读取选择的值),并负载的新的值。这使得反映了我在队列中还收藏了变化。因此,保存功能是越来越影响到的。

现在我需要的是,收藏,我已经在队列中不应该会受到影响,即使收集present已经被重置。

我怎样才能实现?

// code:

MainForm的:

公共类Form1中

 ''一类的队列集合
昏暗oQueueCollection作为新队列(中MyItem)
''BackgroundWorker的实例
DIM BW作为BackgroundWorker的=新的BackgroundWorker()


BackgroundWorker的实例
昏暗m_oBackgroundWorker作为BackgroundWorker的=无

排队一类集合
昏暗m_cQueueCollection随着新队列(中BackgroundworkerController)

昏暗m_cBackgroundworkerController作为新BackgroundworkerController


私有财产将项目作为新项目

'''<总结>
'''获取或设置的项目定价集合。
'''< /总结>
'''<值GT;< /值GT;
'''<返回>< /回报>
'''<说明>< /说明>
公共财产ItemPricingCollection()为集合(中ItemPricing)=新集(中ItemPricing)


私人小组Form1_Load的(BYVAL发件人为对象,BYVALË作为System.EventArgs)把手Me.Load
    初始化化背景下的工人
    m_oBackgroundWorker =新的BackgroundWorker()

    调用完成方法,一旦线程完成它的工作
    m_oBackgroundWorker.WorkerReportsProgress = TRUE


    创建线程,并继续与工艺
    AddHandler的m_oBackgroundWorker.DoWork,AddressOf bw_DoWork

    调用方法的线程的工作完成后,
    AddHandler的m_oBackgroundWorker.RunWorkerCompleted,AddressOf bw_RunWorkerCompleted

结束小组

私人小组SaveItem()
    可见,启动保存该项目。
    MSGBOX(m_cQueueCollection.First()。Item.ItemNo)

    使线程睡眠延迟(在这期间,我们可以使下保存)---只有测试目的
    System.Threading.Thread.Sleep(13000)
结束小组

私人小组bw_DoWork(BYVAL发件人为对象,BYVAL E上DoWorkEventArgs)

    调用保存方法
    SaveItem()

    显示保存/已完成项目的无
    这个ID将assinged所有在该应用程序所需要的电流货号(PK)的地方。
    e.Result = m_cQueueCollection.First()Item.ItemNo和放大器。 完成后

    删除队列中的已完成项目
    m_cQueueCollection.Dequeue()
结束小组

私人小组bw_RunWorkerCompleted(BYVAL发件人为对象,BYVAL E上RunWorkerCompletedEventArgs)
    '显示了结果
    MSGBOX(e.Result)

    检查的收集和禁用计时器,以便不一定运行未
    如果(m_cQueueCollection.Count = 0)然后
        Timer1.Enabled =假
        Timer1.Stop()
    结束如果
结束小组


私人小组的button1_Click(BYVAL发件人为System.Object的,BYVALË作为System.EventArgs)把手Button1.Click
    ThreadPoolTest()

    设置类的属性
    这样做是为了做有队列进行处理内部的多个类/集
    m_cBackgroundworkerController.Item = Me.Item
    m_cBackgroundworkerController.ItemPricingCollection = Me.ItemPricingCollection

    我已经trided
    m_cBackgroundworkerController.Item = DirectCast(Me.Item.clone()项)


    添加收藏到队列
    m_cQueueCollection.Enqueue(m_cBackgroundworkerController)

    允许定时器
    Timer1.Enabled = TRUE

结束小组

私人小组Button2_Click(BYVAL发件人为System.Object的,BYVALË作为System.EventArgs)把手Button2.Click
    Me.Item =无
    Me.ItemPricingCollection.Clear()
结束小组

检查的收集和后台工作,并启动线程过程每隔1秒。
如果线程在运行,它只是退出。

私人小组Timer1_Tick(BYVAL发件人为System.Object的,BYVALË作为System.EventArgs)把手Timer1.Tick
    如果(m_cQueueCollection.Count大于0 AndAlso未m_oBackgroundWorker.IsBusy)然后
        m_oBackgroundWorker.RunWorkerAsync()
    结束如果
结束小组

末级
 

// BackgroundWorkerClass:

 公共类BackgroundworkerController

实现IDisposable



私人共享s_bDisposed为布尔
'''<总结>
'''获取或设置的项目。
'''< /总结>
'''<值GT;< /值GT;
'''<返回>< /回报>
'''<说明>< /说明>
公共属性Item()作为项目=新项目



'''<总结>
'''获取或设置的项目定价集合。
'''< /总结>
'''<值GT;< /值GT;
'''<返回>< /回报>
'''<说明>< /说明>
公共财产ItemPricingCollection()为集合(中ItemPricing)=新集(中ItemPricing)

末级
 

//一类的:

 <序列化()> _
公共类项目
    实现IDisposable

    私人m_sItemNo作为字符串=
   私人sEnvironment code sItemNo的String =
    私人m_bIsChanged为布尔
    私人m_bIsInDatabase为布尔



jw10年底新的集合添加

'''<总结>
'''获取或设置项目编号。
'''< /总结>
'''<值GT;< /值GT;
'''<返回>< /回报>
'''<说明>< /说明>
公共财产货号()为String

    得到
        返回Me.m_sItemNo
    最终获取

    设置(BYVAL值作为字符串)
        如果没有Me.IsLoading然后Me.IsChanged =真
        Me.m_sItemNo =价值
    结束设定

高端物业

'''<总结>
'''获取或设置环境code。
'''< /总结>
'''<值GT;< /值GT;
'''<返回>< /回报>
'''<说明>< /说明>
公共属性环境code()作为字符串

    得到
        返回Me.m_sEnvironment code
    最终获取

    设置(BYVAL值作为字符串)
        如果Me.m_sEnvironment code<>值。然后Me.m_bIsChanged =真
        Me.m_sEnvironment code =价值
    结束设定

高端物业



'''<总结>
'''获取或设置更改标志。
'''< /总结>
'''<值GT;< /值GT;
'''<返回>< /回报>
'''<说明>< /说明>
公共财产IsChanged()作为布尔

    得到
        返回Me.m_bIsChanged
    最终获取

    设置(BYVAL值作为布尔)
        Me.m_bIsChanged =价值
    结束设定

高端物业



'''<总结>
'''获取或设置就是在数据库中的标志。
'''< /总结>
'''<值GT;< /值GT;
'''<返回>< /回报>
'''<说明>< /说明>
公共财产IsInDatabase()作为布尔

    得到
        返回Me.m_bIsInDatabase
    最终获取

    设置(BYVAL值作为布尔)
        Me.m_bIsInDatabase =价值
    结束设定

高端物业

公共重载子的Dispose()实现IDisposable.Dispose

    检查是否处置已经调用
    如果不s_bDisposed然后

        调用Dispose方法
        Me.Dispose(真)

        告诉垃圾收集的对象不需要清理
        GC.Sup pressFinalize(ME)

    结束如果

结束小组

受保护的可重写重载子的Dispose(BYVAL处置作为布尔)

    旗类处置
    s_bDisposed = TRUE

结束小组

末级
 

解决方案

我也面临同样的问题。我从以下链接上心。

<一个href="http://stackoverflow.com/questions/10745026/vb-net-copy-a-list-to-store-original-values-to-be-used-later">VB.Net使用复制的列表来存储原始值后

尝试以下code

 班级设置为一个属性
这样做是为了做有队列进行处理内部的多个类/集
m_cBackgroundworkerController.Item = CTYPE(的DeepCopy(Me.Item)项)
m_cBackgroundworkerController.ItemPricingCollection = CTYPE(的DeepCopy(Me.ItemPricingCollection),集(中ItemPricing))


添加收藏到队列
m_cQueueCollection.Enqueue(m_cBackgroundworkerController)

允许定时器
Timer1.Enabled = TRUE




公共职能的DeepCopy(BYVAL ObjectToCopy作为对象)作为对象

    用纪念品作为新的MemoryStream

        昏暗的BF作为新的BinaryFormatter
        bf.Serialize(MEM,ObjectToCopy)

        mem.Seek(0,SeekOrigin.Begin)

        返回bf.Deserialize(MEM)

    结束使用

端功能
 

Task: I have a requirement(User able to save continuously one after the other without waiting) so i choose multi-threading and i was about to complete that with the Queue concept. But i have stuck up in one scenario.

Task regarding code: There was many collections and objects in the application for which i have created a single Queue class and created a separate collections and objects in that and all those were assigned to the queue class objects. Whenever the user saves the changes all those collections and objects are filled and assigned to the queue collections and objects and added in the queue, So the background worker takes the collections and objects and do the process. This is done to make sure that the values saved are for the correct since there is continuous save.

Scenario: The application has a grid in which the user selects a row and using a Unique Id from it the values are loaded in the collection and bind to the form. So the user will update the values and click on save. Then he clicks on the next row and once the values are loaded he makes the changes again and save.This is where the problems arise.

Since i have assigned all the previous collection to the queue collection, when the user make the changes and clicks on save and he goes for the next row and clicks on that, the collection present already in the application is getting reset(Since the collection is reset for every row selection to load the selected value) and the new values are loaded. This makes the changes reflecting the collection which i have in the queue also. So the save functionality is getting affected in between.

Now i need is the, Collection which i have in the queue should not get affected even when the collection present already gets reset.

How can i achieve?

//Code:

MainForm:

Public Class Form1

''Queue collection of a class
'Dim oQueueCollection As New Queue(Of MyItem)
''Backgroundworker instance
'Dim bw As BackgroundWorker = New BackgroundWorker()


'Backgroundworker instance
Dim m_oBackgroundWorker As BackgroundWorker = Nothing

'Queue collection of a class
Dim m_cQueueCollection As New Queue(Of BackgroundworkerController)

Dim m_cBackgroundworkerController As New BackgroundworkerController


Private Property Item As New Item

''' <summary>
''' Get or set the Item Pricing collection.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property ItemPricingCollection() As Collection(Of ItemPricing) = New Collection(Of ItemPricing)


Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    'Initialize the backgroud worker
    m_oBackgroundWorker = New BackgroundWorker()

    'Call the completed method once the thread completes it work
    m_oBackgroundWorker.WorkerReportsProgress = True


    'Create thread and continue with the process
    AddHandler m_oBackgroundWorker.DoWork, AddressOf bw_DoWork

    'Method called after the thread work completes
    AddHandler m_oBackgroundWorker.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted

End Sub

Private Sub SaveItem()
    'Shows the item that starts the save.
    MsgBox(m_cQueueCollection.First().Item.ItemNo)

    'Makes the thread to sleep for the delay(In between we can make the next save)--- Testing purpose only
    System.Threading.Thread.Sleep(13000)
End Sub

Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)

    'Calls the save method
    SaveItem()

    'Shows the saved/Completed item's No
    'This Id will be assinged to all the places in which the application needs the current itemno(PK).
    e.Result = m_cQueueCollection.First().Item.ItemNo & " is Completed"

    'Removes the Completed item in queue
    m_cQueueCollection.Dequeue()
End Sub

Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
    'shows the result
    MsgBox(e.Result)

    'Check the collection and disable the timer in order not to run un necessarily
    If (m_cQueueCollection.Count = 0) Then
        Timer1.Enabled = False
        Timer1.Stop()
    End If
End Sub


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    'ThreadPoolTest()

    'Sets the class to a property
    'this is done in order to have multiple class/collections inside the queue for processing
    m_cBackgroundworkerController.Item = Me.Item
    m_cBackgroundworkerController.ItemPricingCollection = Me.ItemPricingCollection

    'I have trided
    'm_cBackgroundworkerController.Item = DirectCast(Me.Item.clone(), Item)


    'Adds the collection to the queue
    m_cQueueCollection.Enqueue(m_cBackgroundworkerController)

    'enables the timer
    Timer1.Enabled = True

End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    Me.Item = Nothing
    Me.ItemPricingCollection.Clear()
End Sub

'Checks the collection and background worker and start the thread process for every 1 second.
'If the thread is running it just exits.

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    If (m_cQueueCollection.Count > 0 AndAlso Not m_oBackgroundWorker.IsBusy) Then
        m_oBackgroundWorker.RunWorkerAsync()
    End If
End Sub

End Class

//BackgroundWorkerClass:

Public Class BackgroundworkerController

Implements IDisposable



Private Shared s_bDisposed As Boolean
''' <summary>
''' Get or set the item.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>  
Public Property Item() As Item = New Item



''' <summary>
''' Get or set the Item Pricing collection.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property ItemPricingCollection() As Collection(Of ItemPricing) = New Collection(Of ItemPricing)

End class

//One of the class:

<Serializable()> _
Public Class Item
    Implements IDisposable

    Private m_sItemNo As String = ""
   Private sEnvironmentCode sItemNo As String = ""
    Private m_bIsChanged As Boolean
    Private m_bIsInDatabase As Boolean



'jw10 end new collections added

''' <summary>
''' Get or set the Item Number.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property ItemNo() As String

    Get
        Return Me.m_sItemNo
    End Get

    Set(ByVal value As String)
        If Not Me.IsLoading Then Me.IsChanged = True
        Me.m_sItemNo = value
    End Set

End Property

''' <summary>
''' Get or set the environment code.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property EnvironmentCode() As String

    Get
        Return Me.m_sEnvironmentCode
    End Get

    Set(ByVal value As String)
        If Me.m_sEnvironmentCode <> value Then Me.m_bIsChanged = True
        Me.m_sEnvironmentCode = value
    End Set

End Property



''' <summary>
''' Get or set the changed flag.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property IsChanged() As Boolean

    Get
        Return Me.m_bIsChanged
    End Get

    Set(ByVal Value As Boolean)
        Me.m_bIsChanged = Value
    End Set

End Property



''' <summary>
''' Get or set the is in database flag.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property IsInDatabase() As Boolean

    Get
        Return Me.m_bIsInDatabase
    End Get

    Set(ByVal Value As Boolean)
        Me.m_bIsInDatabase = Value
    End Set

End Property

Public Overloads Sub Dispose() Implements IDisposable.Dispose

    'Check to see if dispose has already been called
    If Not s_bDisposed Then

        'Call the dispose method 
        Me.Dispose(True)

        'Tell the garbage collector that the object doesn't require cleanup 
        GC.SuppressFinalize(Me)

    End If

End Sub

Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)

    'Flag class as disposed 
    s_bDisposed = True

End Sub

End Class

解决方案

I have face the same problem. I got the idea from below link.

VB.Net Copy a list to store original values to be used later

Try the below code

'Sets the class to a property
'this is done in order to have multiple class/collections inside the queue for processing
m_cBackgroundworkerController.Item = CType(DeepCopy(Me.Item), Item)
m_cBackgroundworkerController.ItemPricingCollection = CType(DeepCopy(Me.ItemPricingCollection), Collection(Of ItemPricing))


'Adds the collection to the queue
m_cQueueCollection.Enqueue(m_cBackgroundworkerController)

'enables the timer
Timer1.Enabled = True




Public Function DeepCopy(ByVal ObjectToCopy As Object) As Object

    Using mem as New MemoryStream

        Dim bf As New BinaryFormatter
        bf.Serialize(mem, ObjectToCopy)

        mem.Seek(0, SeekOrigin.Begin)

        Return bf.Deserialize(mem)

    End Using

End Function

这篇关于父集合的参考影响分配的集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆