Hi:

I am using Canon SDK for camera control. Everything works fine until I start using timers or delays. Let me explain:

If I use a regular button to call the take_picture method on the SDK everything works fine.

But when I use a Timer, DispatcherTimer or any other kind of delay that I could think of an error about delagates and garbage collector pops up:

A callback was made on a garbage collected delegate of type 'WPF!EDSDKLib.EDSDK+EdsObjectEventHandler::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.

When I call the method from another thread the error comes up.

The SDK uses event handlers to know if a file is ready (I am no expert in this particular topic)

Here are the classes that I am using.

The SDK class is (with only the relevant lines):

public class EDSDK

    {

        public delegate uint EdsObjectEventHandler(uint inEvent, IntPtr inRef, IntPtr inContext);

        [DllImport("EDSDK.dll")]

        public extern static uint EdsSetObjectEventHandler(IntPtr inCameraRef, uint inEvnet,

             EdsObjectEventHandler inObjectEventHandler, IntPtr inContext);

	}

Then I made my own class called CanonCamera that has various methods:

p

ublic class CanonCamera

    {

 	public bool open_camera(){

   		err = EDSDK.EdsSetObjectEventHandler(cameraDev, EDSDK.ObjectEvent_All, objectEventHandler, new IntPtr(0));

	}

 	public uint objectEventHandler(uint inEvent, IntPtr inRef, IntPtr inContext)

        {

 	switch (inEvent)

            {

                case EDSDK.ObjectEvent_DirItemCreated:

                    downloadImage(inRef);

		break;
	}

	 private uint downloadImage(IntPtr directoryItem)

        {

		//downloads image

	}

}

And on my form I have:

public partial class FRM_Video_Recording : Window

    {

	static CanonCamera canonCamera = new CanonCamera();

	public DispatcherTimer Timer_foto = new DispatcherTimer();

  	 private void Window_Loaded(object sender, RoutedEventArgs e)

        {

            Timer_foto.Tick += new EventHandler(Timer_foto_Tick);

            Timer_foto.Interval = new TimeSpan(0, 0, 10);

            Timer_foto.Start();

	}

   private void Timer_foto_Tick(object sender, EventArgs e)

        {
		canonCamera.open_camera();
canonCamera.take_picture();//then I proceed to take a picture and when the             //objectEventHandler is called I get the error.

}

As I mentioned if i put the open_camera line and take_picture_line on a button it works perfectly, the only problem is if I put it inside the timer or any other delay mechanism.

I know I have to save the delegate on some variable, but where and how do I do this.

Thanks a lot.

Fernando

Sounds like the CanonCamera object (or at least the SDK object it wraps) wants its methods executed on the thread in which it was created.
You might need to invoke a method in your timer(s) to run camera operations.

private void Timer_foto_Tick(object sender, EventArgs e)
{
    this.Invoke(TakeFoto); // forces execution of TakeFoto on to same thread as "this" object.
}

private void TakeFoto()
{
    canonCamera.open_camera();
    canonCamera.take_picture();
}

Note: this is for a windows forms app.
Not quite sure if this is true for a WPF app (which is what I think you are writing).

Hi,

The Canon SDK was written in unmanaged code (OS raw environment). .NET uses application domain to somehow partition the threads into groups. This concept can run fine inside .NET framework.

The EDSDK is not in-bound call. Therefore it uses a pointer to hook to the caller. This is cameraPointer you send in to EDSDK. The pointer you send in is more like WinHandler. Therefore secondary thread not in the OS's same address space.

Solution:
1. Keep the EDSDK event-handler in the form's main thread.
2. Create a custom event for EDSDK's eventHandler to fire as soon as message is received.
2. Run a dummy-wait-thread (secondary-thread): delays and wait for event fired, and continue your process.


EDSDK can be tricky.

This article has been dead for over six months. Start a new discussion instead.