When adding controls and components to the form in designer, Visual Studio and the Form class implicitly takes care of several tasks. One task is checking whether a class implements Iinitialize. If it does, VS adds code to call BeginInit and EndInit. Another item it does is call dispose on an item if it implements IDisposable.
The drivers implement IDisposable and if dispose is not called, it will not be able to release all of its resources.
If you're objective is to avoid using the main UI thread, there are several methods to do this. As you discovered the Read and Write methods will hold until the command is completed. There is also 2 other commands that do not block, these are BeginRead and BeginWrite.
BeginRead and BeginWrite comes with a risk. Since the driver can processor commands several magnitudes faster than the PLC can process and respond to them, the driver must use a queue which is 30 items deep. A BeginRead or BeginWrite takes about 0.1ms to process. A PLC typically takes between 5 and 20ms to process a command. So if you have a loop calling BeginWrite, within 3ms you can fill tyhe queue which is faster than the PLC can process even the first command. So it is up to the user to properly throttle BeginRead and BeginWrites to ensure it doesn't fill the queue.
Another approach, which you are implementing is to use a secondary thread and use the Write so the driver throttles the commands. This is a perfectly acceptable method, but it is not the most efficient to create a new instance of the driver. You can use a driver instance that was added to the form.
In your code that is running on a background thread, are you positive you are not creating multiple background threads that stay in the loop? You can check this by pausing your application in VS, then dropping down the list of threads to see how many there are.
Also a continuous loop that has no exit path or "rest" period is not the most efficient. The preferred and more efficient method is to use a System.Threading.EventWaitHandle
The EventWaitHandle will hold a thread without maxing out a threads CPU time and release when told to. This is an example of how to use it:
Private HoldRelease As New System.Threading.EventWaitHandle(False, Threading.EventResetMode.AutoReset)
Private ExitThread as boolean
--------------- Your Background worker thread
Do while Not ExitThread
HoldRelease.Reset
HoldRelease.waitone(5000)
If PLC_IO_Write.bNewHour Then
PLC_IO_Write.bNewHour = False
EthernetIPforMicro800Com1.Write("PlateCnt_PerHr_Tick", "1")
End If
End While
--------- Another area of your code
If PLC_IO_Write.bNewHour Then
HoldRelease.Set
End If