I am using a background thread to initialize an instrument over USB. The UI hangs when I try to open the device. I would expect the background thread to pause when calling Open on the device, but not the UI thread. I am testing this with no UI interaction from the background thread. I don't know how to debug the problem, and it's too broad a question, but perhaps someone has seen something like this before. There is nothing wrong with the ActiveX interop as far as I know, the device works correctly. This is the general approach:
using System;
using FancyVoltmeterLibrary;
namespace SOQuestion
{
public class MeterClass
{
private FancyVoltmeter meter;
private Thread meterThread;
public MeterClass()
{
// Create instance of ActiveX/COM object.
meter = new FancyVoltmeter();
meterThread = new Thread(UpdateMeter);
meterThread.Name = "Meter Thread";
meterThread.Priority = ThreadPriority.Normal;
meterThread.IsBackground = true;
meterThread.Start();
}
private void UpdateMeter()
{
while(true)
{
Thread.Sleep(1000);
if(!meter.IsOpen())
{
// Meter may be powered off here.
// The call to Open takes about 1 second.
// UI hangs during the call???
meter.Open();
}
// code to read meter goes here.
}
}
}
}
Edit: Perhaps unclear what I meant. By 'hang' I should say 'freezes momentarily'.
onReceive(Context, Intent) method is called within the main thread by default. So you can use it to update the UI on the main thread.
In this case, to update the UI from a background thread, you can create a handler attached to the UI thread, and then post an action as a Runnable : Handler handler = new Handler(Looper. getMainLooper()); handler. post(new Runnable() { @Override public void run() { // update the ui from here } });
Background threads are identical to foreground threads with one exception: a background thread does not keep the managed execution environment running. Once all foreground threads have been stopped in a managed process (where the .exe file is a managed assembly), the system stops all background threads and shuts down.
To specify the thread on which to run the action, construct the Handler using a Looper for the thread. A Looper is an object that runs the message loop for an associated thread. Once you've created a Handler , you can then use the post(Runnable) method to run a block of code in the corresponding thread.
Does meter require running in an STA? Is the call to Open() actually being marshalled back to the UI thread for this reason?
You can verify this is true by looking at the callstack of the hung UI thread in the debugger.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With