Click here to Skip to main content
15,884,388 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hello everybody. My problem goes like this:
I have a DependencyProperty, which when set while on the correct thread (Dispatcher.CheckAccess returns true) throws an InvalidOperationException ("The calling thread cannot access this object because a different thread owns it.").

C#
public static class PicGetter
{
    public static ConcurrentQueue<TFileInfo> cq = new ConcurrentQueue<TFileInfo>();

    public static void GetPix()
    {
        Thread tron = new Thread(_GetPix);
        tron.Name = "Thumb obtainer";
        tron.IsBackground = true;
	tron.Start();
    }

    public static void _GetPix()
    {
	TFileInfo f;
	while (!cq.IsEmpty)
	{
            if (cq.TryDequeue(out f))
		f.Thu();
	}
    }

    public static void Thu(this TFileInfo f)
    {
	BitmapSource bs;
	if (Misc.Windows7)
	{
            ShellFile sf = ShellFile.FromFilePath(f.FullName);
            bs = sf.Thumbnail.ExtraLargeBitmapSource;
	}
	else if (f.isPic())
	    bs = new Bitmap(Image.FromFile(f.FullName)).ToBitmapSource();
	else
	   bs = Icon.ExtractAssociatedIcon(f.FullName).ToBitmap().ToBitmapSource();

        f.Dispatcher.Invoke(new Action<BitmapSource, TFileInfo>((b, t) => t.Thumb = b), bs, f);
    }
}

public class TFileInfo : DependencyObject
{
    public BitmapSource Thumb
    {
	get { return (BitmapSource)GetValue(ThumbProperty); }
	set
	{
	    //MessageBox.Show(Dispatcher.CheckAccess() + "\n" + this.Dispatcher.Thread.ManagedThreadId + "\n" + Thread.CurrentThread.ManagedThreadId);
	    SetValue(ThumbProperty, value); }
	}
    public static readonly DependencyProperty ThumbProperty =
	DependencyProperty.Register(
	"Thumb",
	typeof(BitmapSource),
	typeof(TFileInfo),
	new UIPropertyMetadata((new Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream("BiblioRap.Images.BlankDoc.png"))).BitmapSource()));
}


I cannot for the life of me figure out why it does so. The exception's stack trace ends "at System.Windows.Threading.Dispatcher.VerifyAccess()".
Posted
Updated 16-Jun-16 3:49am
Comments
Sergey Alexandrovich Kryukov 20-Jul-12 11:23am    
What tells you this exception is not supposed to be thrown? :-)
--SA
claudiu2323 20-Jul-12 11:26am    
Because I am invoking it on the Thread it was created on, so it shouldn't say otherwise.
Amir Mahfoozi 24-Jul-12 6:40am    
Hi Claudiu, does my answer at this page help you : http://www.codeproject.com/Answers/409837/Creating-trace-log-file-using-threading#answer4
claudiu2323 25-Jul-12 8:47am    
It just might. I can't try it out right now, but hopefully I'll test it in a few days. Anyway, thank you all for the answers. Post it as a solution, so I can accept it if it works.

The property System.Windows.Threading.Dispatcher.CheckAccess only tells you that the calling thread is the thread associated with this Dispatcher (the instance of the dispatcher used as "this" in the call of this instance property). It does not tell you that you can access UI methods/properties from this thread — if this is not the thread running the same UI, you never can.

What do you thing is the purpose of the dispatcher? To cause the UI to call some delegate in the UI thread, through Dispatcher.Invoke or Dispatcher.BeginInvoke.

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

—SA
 
Share this answer
 
Comments
claudiu2323 20-Jul-12 11:36am    
But you see, I am trying to cause the UI to call a delegate in the UI Thread through Dispatcher.Invoke:

f.Dispatcher.Invoke(new Action<bitmapsource, tfileinfo="">((b, t) => t.Thumb = b), bs, f);

Am I doing something wrong ?
Sergey Alexandrovich Kryukov 22-Jul-12 14:36pm    
If there exception in this line or the target of invocation? Try to put a break point at the statement t.Thumb = b; will it throw exception?
--SA
Sergey Alexandrovich Kryukov 22-Jul-12 14:39pm    
How did you obtain the Dispatcher for TFileInfo? This could be wrong, but you did not show this part of code.
--SA
claudiu2323 22-Jul-12 16:28pm    
Well, TFileInfo is a DependencyObject, so I just get it's member Dispatcher (TFileInfo.Dispatcher);
Second, the line above ( f.Dispatcher.Invoke(new Action<bitmapsource,>((b, t) => t.Thumb = b), bs, f); )
continues to the invocation, then while on the main thread, the UI thread, where supposedly I should be able to access my object, that DependencyProperty Setter internally calls VerifyAccess, after a series of calls (I have shown the list earlier) which declares an OperationInvalidException, as stated previously. It seems irrational, because when I set the DependencyProperty directly from the main (UI) thread, it works flawlessly, however, when I set it after calling Invoke/BeginInvoke from another thread, it throws this nasty piece of craft Exception. Am I doing it wrong ?
claudiu2323 20-Jul-12 11:41am    
Also, this is the stack trace from the exception details window:
at System.Windows.Threading.Dispatcher.VerifyAccess()
at System.Windows.Controls.Image.OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp)
at System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange)
at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
at System.Windows.Data.BindingExpression.ScheduleTransfer(Boolean isASubPropertyChange)
at MS.Internal.Data.ClrBindingWorker.NewValueAvailable(Boolean dependencySourcesChanged, Boolean initialValue, Boolean isASubPropertyChange)
at MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState(Int32 k, ICollectionView collectionView, Object newValue, Boolean isASubPropertyChange)
at MS.Internal.Data.PropertyPathWorker.OnDependencyPropertyChanged(DependencyObject d, DependencyProperty dp, Boolean isASubPropertyChange)
at MS.Internal.Data.ClrBindingWorker.OnSourceInvalidation(DependencyObject d, DependencyProperty dp, Boolean isASubPropertyChange)
at System.Windows.Data.BindingExpression.HandlePropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args)
at System.Windows.Data.BindingExpressionBase.OnPropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args)
at System.Windows.Data.BindingExpression.OnPropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args)
at System.Windows.DependentList.InvalidateDependents(DependencyObject source, DependencyPropertyChangedEventArgs sourceArgs)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
at BiblioRap.TFileInfo.set_Thumb(BitmapSource value) in C:\Users\Red Cat\Desktop\bibliorap\TFileInfo.cs:line 94
at BiblioRap.PicGetter.<Thu>b__0(BitmapSource b, TFileInfo t) in C:\Users\Red Cat\Desktop\bibliorap\TFileInfo.cs:line 52
Hi Claudiu,
Does my answer at this page help you :
http://www.codeproject.com/Answers/409837/Creating-trace-log-file-using-threading#answer4

Good Luck
 
Share this answer
 
Comments
claudiu2323 5-Aug-12 5:14am    
I'm sorry, but it does not work. It gives the same error and situation as before.
Hi,
even if this question is four years old ...

Try to freeze the bitmap before using it.

See also: this.Dispatcher.Invoke gives me "The calling thread cannot access this object because a different thread owns it"[^]

and: Freezable.Freeze Method (System.Windows)[^]
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900