How to get BitmapImage into UI thread via Dispatcher.BeginInvoke?

WoodManEXP 150 Reputation points
2026-11-09T22:36:32.63+00:00

Hi,

Can you help me understand why a C# call to Dispatcher.BeginInvoke is throwing this exception:

System.Reflection.TargetParameterCountException: 'Parameter count mismatch.

The code snippet, initially lifted from a GitHub project, looks like this

    // Get BitmapImage from OpenCVSharp webcam capture
	var converted = Convert(BitmapConverter.ToBitmap(matImage));

	// Throw this to UI thread to update the <Image> element
	UI_Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action<BitmapImage>((converted) =>
	{
	    imgViewport.Source = converted; // converted;
	}));
	

The bitmap is being processed/augmented by a long-running process on another thread, don’t want to be doing that on the UI thread, and when that process completes the app intends to update the <Image> element with the processed bitmap.

Whenever BeginInvoke is called the Parmeter count mismatch exception is thrown. I’ve researched this quite a bit and tried several ways to correct. Can anyone help me understand how to get the bitmap into the UI thread?

TY!

Developer technologies | C#
Developer technologies | C#

An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.

0 comments No comments

Answer accepted by question author
Brian Pham (WICLOUD CORPORATION) 1,340 Reputation points Microsoft External Staff Moderator
2026-11-10T03:10:50.7133333+00:00

Hi @WoodManEXP ,

Thanks for sharing the code snippet.

The exception comes from the delegate type. new Action<BitmapImage>(...) expects one argument, but the BeginInvoke overload you're calling doesn't pass any, so WPF complains about the parameter count. Your lambda parameter is also named converted, which hides the variable you actually want to use.

Switch to a plain Action and let the lambda capture the bitmap:

BitmapImage converted = Convert(BitmapConverter.ToBitmap(matImage));
if (converted.CanFreeze) converted.Freeze();
 
imgViewport.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
    imgViewport.Source = converted;
}));

Please don't skip the Freeze() call. A BitmapImage created on a background thread can't be used on the UI thread unless it's frozen. Without it, you'll fix this error and then hit a "different thread owns it" exception right after. If your Convert method loads the image from a stream, also set CacheOption = BitmapCacheOption.OnLoad before EndInit(). Otherwise Freeze() may fail.

If you found my response helpful or informative, I would greatly appreciate it if you could follow this guide for your confirmation.

Thank you.

Was this answer helpful?

1 person found this answer helpful.

Answer accepted by question author

AI answer

2026-11-09T22:37:24.5966667+00:00

Replace the parameterized Action<BitmapImage> with a parameterless Action that captures converted, and freeze the background-created image before dispatching it to the UI thread.

// Runs on the background thread.
BitmapImage converted = Convert(BitmapConverter.ToBitmap(matImage));

if (converted.CanFreeze)
    converted.Freeze();

imgViewport.Dispatcher.BeginInvoke(
    DispatcherPriority.Normal,
    new Action(() =>
    {
        imgViewport.Source = converted;
    }));

Why the exception occurs

Your delegate declares one required parameter:

new Action<BitmapImage>((converted) => { ... })

However, the selected BeginInvoke(DispatcherPriority, Delegate) overload supplies no arguments to that delegate. Consequently, invocation expects one parameter but receives zero, producing TargetParameterCountException. That exception specifically indicates that the invocation's supplied parameter count differs from the delegate's expected count.^1^

The captured-variable version uses an Action with zero parameters, matching that overload. BeginInvoke then queues the UI update asynchronously on the dispatcher's thread.^2^

Using imgViewport.Dispatcher also ensures that the dispatcher belongs to the UI element being updated.

Alternative: pass the bitmap as an explicit argument

If a parameterized delegate is preferable, use the overload that accepts an argument:

if (converted.CanFreeze)
    converted.Freeze();

imgViewport.Dispatcher.BeginInvoke(
    DispatcherPriority.Normal,
    new Action<BitmapImage>(bitmap =>
    {
        imgViewport.Source = bitmap;
    }),
    converted);

Here, converted is explicitly supplied as the argument for the delegate's bitmap parameter. Do not name the lambda parameter converted when an outer variable has the same name; although legal in some contexts, it obscures which value is being used.

Cross-thread image ownership

Fixing the parameter count does not by itself make an image created on a worker thread transferable. WPF UI objects have thread affinity, and BitmapImage participates in WPF's Freezable model. An unfrozen Freezable cannot be shared across threads; a frozen one can.^3^

Therefore:

  1. Complete the conversion and all image modifications on the worker thread.
  2. Check CanFreeze and call Freeze() there.
  3. Dispatch only the short imgViewport.Source assignment.
  4. Do not modify the image after freezing it.

If CanFreeze is false, create or copy the WPF image on the UI thread instead, while leaving the expensive OpenCV processing on the worker thread. The Image.Source property accepts an ImageSource, including a BitmapImage.^4^


References

  1. TargetParameterCountException Class-Definition
  2. Dispatcher.BeginInvoke Method-Definition
  3. Freezable Objects Overview
  4. Defines the Source property of the Image control, which gets or sets the ImageSource for the image.
AI-generated content may be incorrect. Read our transparency notes for more information.

Was this answer helpful?

1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.