views:

190

answers:

3

I get a null exception if I try to pass a null parameter to a delegate during an invoke. Here's what the code looks like:

        public void RequestPhoto()
        {
            WCF.Service.BeginGetUserPhoto(Contact.UserID,
                new AsyncCallback(RequestPhotoCB), null);
        }

        public void RequestPhotoCB(IAsyncResult result)
        {
            var photo = WCF.Service.EndGetUserPhoto(result);
            UpdatePhoto(photo);
        }

        public delegate void UpdatePhotoDelegate(Binary photo);
        public void UpdatePhoto(Binary photo)
        {
            if (InvokeRequired)
            {
                var d = new UpdatePhotoDelegate(UpdatePhoto);
                Invoke(d, new object[] { photo });
            }
            else
            {
                var ms = new MemoryStream(photo.ToArray());
                var bmp = new Bitmap(ms);
                pbPhoto.BackgroundImage = bmp;
            }
        }

The problem is with the line:

Invoke(d, new object[] { photo });

If the variable "photo" is null. What is the correct way to pass a null parameter during an invoke? Thanks!

A: 

Is Binary a nullable type? I'm not sure if it is....you may have to pass in a nullable Binary instead.

Nate Noonen
Yes, I do believe it is a nullable type (System.Data.Linq.Binary). var photo = WCF.Service.EndGetUserPhoto(result); returns a null if there is no photo (binary), with no exception.
Rodney Burton
A: 

OK I figured it out. The problem was NOT with passing the null parameter to the delegate like I thought. The problem was with the delegate executing it was causing a null exception on the line:

var ms = new MemoryStream(photo.ToArray());

I didn't realize the problem was there because it was crashing on the Invoke line.

So I changed the UpdatePhoto method as follows:

public void UpdatePhoto(Binary photo)
        {
            if (InvokeRequired)
            {
                var d = new UpdatePhotoDelegate(UpdatePhoto);
                Invoke(d, new object[] { photo});
            }
            else
            {
                if (photo != null)
                {
                    var ms = new MemoryStream(photo.ToArray());
                    var bmp = new Bitmap(ms);
                    pbPhoto.BackgroundImage = bmp;
                }
            }
        }

And all is well!

Rodney Burton
Next time you run into an issue with your Invoke, don't forget to check your InnerException - it should clarify the issue a bit more quickly!
mattdekrey
+1  A: 

Just for the benefit of others, you can pass null arguments to delegates (if the type allows it? Clarification needed here). In your case, IAsyncResult will allow it.

As for the debugging, the exception occurs on Invoke because you are debugging on a given Thread A, the exception occurs on Thread B. You can breakpoint multiple threads. Breakpoint the Thread B code and you will see the exception closer to or on the source.

Notice though that your debugger will jump around if multiple threads are running code at the same time. Debugging in multiple threads is always at least a little tricky, but satisfying when you solve the problems.

You could also further improve your answer code to check the null before it checks the InvokeRequired, as this is thread-independent to your logic (your code checks it just prior to use, after Invoking). This will save pushing the Invoke onto the message pump (assuming WinForms).

Adam