Rapi2.dll version 2.0 WinCE Thread Problem

Mar 26, 2012 at 10:26 AM

Hello people,

First of all I'll like to thank you sharing this wonderful piece of software with us.
Currently busy testing and implementing version 2.0 into our application and it works great.
However the connection to a WinCE device seems to fail whenever it connects through an event.
When i poll for a device, and connect when found, there is no problem. But when i wait for an event to occur and connect from inside the event (or let the Main thread handle the connection with a delegate) i receive an error "Cannot perform this action on a disconnected device".

Any idea?

Thanks for now. 

Coordinator
Apr 20, 2012 at 9:39 PM

Sorry for the delay in getting this tested. Check the first source code example in the Documentation tab. Using this code, I was able to get a valid and usable RemoteDevice when not having any device connected at program startup and then connecting a device. On my Win7 machine, it took up to 10 seconds to fire the event. I was able to connect and disconnect the device multiple times without problems.

Apr 23, 2012 at 10:45 AM

Dear dahall,

I implemented the part that is described on the documentation tab, and it works great on a Win Forms application.
But when i implement this on a console based application the device cannot connect while the application is running, when i close the application the device successfully connects to the computer.

Is this an know issue?

Coordinator
Apr 23, 2012 at 5:08 PM

I haven't tested it in a console app. I'll do that today and report back.

Coordinator
Apr 24, 2012 at 6:54 AM

I introduced a problem with the pattern I used to make sure the events all fire in the same thread where now in applications without a message pump, like a console, the events now hang. I am playing with some ideas for working around this, but haven't had success yet. I'll post an update to version 2.0 once I have something working.

Apr 24, 2012 at 8:22 AM

Thanks for the quick response.
For now i fixed it by porting the console application to a winform application.

Keep me posted,

Apr 24, 2012 at 3:50 PM

Has this issue anything to do with the fact that CE devices connect normally but the properties of the device object not being available?
If not, what could it be?
I posted my testcode below, the device connects but when i try to read a property from the object it returns "Could not ... on a disconnected device"

Imports System.Devices

Public Class Form1
    Private WithEvents _devicemanager As New RemoteDeviceManager
    Private _device As RemoteDevice

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    End Sub

    Private Sub RemoteDeviceManager_Connected(ByVal sender As Object, ByVal e As System.Devices.RemoteDeviceConnectEventArgs) Handles _devicemanager.DeviceConnected
        _device = e.Device
    End Sub

    Private Sub RemoteDeviceManager_Disconnected(ByVal sender As Object, ByVal e As System.Devices.RemoteDeviceConnectEventArgs) Handles _devicemanager.DeviceDisconnected
        _device = e.Device
    End Sub
End Class

Coordinator
Apr 24, 2012 at 9:13 PM

This should all be corrected in the 2.0 release posted today.

May 2, 2012 at 11:39 AM

hi,

i'm too getting the 'This operation cannot be completed on a disconnected device.'

I use Backgroundworker to show progressbar while copying and syncing PDA and sql server. Still cannot go through even I use _Connected,_Disconnected events

May 2, 2012 at 3:03 PM

I'm also getting this exception in the latest release. I'm using a WPF project and using Target CPU is x84 on a x64 system for your information.

Coordinator
May 3, 2012 at 3:05 PM

ranjan250 and SilenceTi, can you provide more information about how you are calling the constructor and then how you are catching the events? I'm having a problem duplicating this error. Some code would be awesome then I'm not wasting time coding stuff that may not even be the same.

May 4, 2012 at 9:59 AM

I create the RemoteDeviceManager on the main WPF thread and also calling the FirstConnectedDevice method on this thread. When I need to transfer some file to a WinCE device I use Task.Factory.StartNew to transfer some files so I won't block the UI.

  This operation cannot be completed on a disconnected device. 

   at System.Devices.RemoteDevice.get_ISession() in C:\Projects\OpenSource\_SVN\RAPI2\RAPI2\RAPI2\RemoteDevice.cs:line 806
   at System.Devices.RemoteFile.Exists(RemoteDevice device, String path) in TransferFileViewModel.vb:line 111
   at System.Threading.Tasks.Task.InnerInvoke()   at System.Threading.Tasks.Task.Execute()

When I create the RemoteDeviceManager on a MTA Thread I'm also getting this exception. In the 1.3 version this solution worked.

The moment I do everything on the UI thread everything works but it will block the UI on long processes.

May 4, 2012 at 10:19 AM

Hi ,

thanks for your reply. this is the code in my program.

 

private RemoteDeviceManager mgr;

private RemoteDevice dev;

 

public Form1()//CONSTRUCTOR

        { 

          InitializeComponent(); 

          mgr = new RemoteDeviceManager(); 

          mgr.DeviceConnected += mgr_DeviceConnected; 

          mgr.DeviceDisconnected += mgr_DeviceDisconnected;
        } 

      private void mgr_DeviceConnected(object sender, RemoteDeviceConnectEventArgs e)

        { 

          dev = e.Device; 

          this.OnConnection(true); 

      }
        private void mgr_DeviceDisconnected(object sender, RemoteDeviceConnectEventArgs e) 

      { 

          dev = e.Device; 

          this.OnConnection(false); 

      }
        private void OnConnection(bool connected) 

      { 

          if (connected) 

              statusLabel.Text = dev.Name + " is now connected"; 

          else               

statusLabel.Text = "No devices are connected."; 

      }

 

//I use a BackgroundWorker in my program.

private void btnSyncServer_Click(object sender, EventArgs e) //Button Click Event

      { 

          backgroundWorker1.RunWorkerAsync();

        }

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 

      { 

        pic.Enabled = true;//Shows an Loading GIF Image 

      }
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

        {

            pic.Enabled = false;

        }

 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)

        {

                   sync(); 

         }

  private void sync()

        {

//THIS IS THE PLACE WHERE THE ERROR GIVES  'This operation cannot be completed on a disconnected device.'

  RemoteFile.Copy(dev, "\\Program Files\\MySetup", "D:\\"+ "\\AppDB.sdf", true); //TRYING TO COPY THE .SDF FILE FROM PDA TO D:\ DRIVE.

 

{

//PROCESS OF SYNCHRONIZATION

}

  }

Coordinator
May 4, 2012 at 5:02 PM
Edited May 4, 2012 at 5:05 PM

So the answer for both situations is simple. The 1.3 library was not thread-safe. It was working on additional threads by accident and is not consistent. The 2.0 library contains all calls and responses on one thread where it knows the underlying COM objects are valid. Where both of you are accessing a RemoteDevice instance on a different thread, use the following code before referring to it:

using (RemoteDeviceManager tr = new RemoteDeviceManager())
{
   using (RemoteDevice tdev = tr.Devices.FirstConnectedDevice)
   {
      if (tdev != null)
         RemoteFile.Copy(tdev, dfn, lfn, true); // or whatever else
   }
}

This should execute quickly as the COM library is already loaded.

May 8, 2012 at 8:00 PM

Hi dahall,

I'm still getting the same "connection issue" as the last release (ie. same issue on 1.2 and 2.0). 

When the device is present and accounted for when the Winform app starts - no problems - scenario 1. However, if the app starts without the device connected, and the device is connected later.... getting the "This operation cannot be completed on a disconnected device." error - scenario 2.

For what its worth, a call to get the device name responds correctly in both scenarios above.  However, when reading registry values on the CE device it reads correctly in scenario 1 but returns a bogus value in the scenario 2 (no surprise there).

I'm using the same technique as you posted for the example.

The issue shows up regardless of the workstation OS (Win7, XP.).  The device is a Motorola MT2090 running CE5.

If I can get past this one single issue then I'm golden.  When working, your wrapper works great!

May 14, 2012 at 11:00 AM

Dear dahall,

I've been busy lately writing code that includes the latest version of RAPI2.dll and still have issues when accessing a device (WM/CE) from within a thread.

When i use the code above, (the using part...) inside a (worker)thread i receive InvalidCastExceptions thrown by IRAPIDesktop.


   bij System.Devices.Interop.IRAPIDesktop.Advise(IRAPISink pISink, Int32& pdwContext)
   bij System.Devices.RemoteDeviceManager..ctor()
   bij Rapi2TestProject.Form1.WorkThreadFunction() in C:\Projects\Emd\trunk\Rapi2TestProject\Form1.cs:regel 42
   bij System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   bij System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   bij System.Threading.ThreadHelper.ThreadStart()

 

Am i doing something wrong?

Coordinator
May 15, 2012 at 5:00 AM

If you are using threads, you must put the MTAThread attribute on the Main() method of your application. Check the Form2.cs file in the RAPIDeviceUI project under Source Code for an example of using a thread to gather device information.

May 15, 2012 at 8:33 AM

That worked!
Thx

May 25, 2012 at 8:55 PM
Edited May 25, 2012 at 8:58 PM

I tried changing to the MTAThread, and the connection to the device worked every time, regardless if the device was present on application start or not.

However, now any "OLE" calls, like bringing up a open file dialog breaks.  So, still not solved the issue.

(try adding a open file dialog to the sample project, Form2.cs above and you should see the same thing)

System.Threading.ThreadStateException was unhandled
  Message="Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process."

Developers writing for Office products call COM objects all day long without issues - not sure why the RAPI2 wrapper is breaking doing the same type of thing...

Any other ways out that can be suggested?