8 Replies - 1073 Views - Last Post: 01 June 2016 - 05:02 PM Rate Topic: -----

#1 sk8ermeb   User is offline

  • D.I.C Head
  • member icon

Reputation: 20
  • View blog
  • Posts: 133
  • Joined: 23-March 10

wpf tasks/threading Objects from different threads

Posted 31 May 2016 - 02:33 PM

Hello,
I have been looking everywhere including C# books, and I cannot figure out how to access a property of an object from a thread other than the one it was created on (or a different way of accomplishing my overall task. I have read that you cannot access an object if it was created on another thread, so any help would be greatly appreciated.

Basically I am trying to preload an image buffer into the GPU using a BitmapCacheBrush. I have all this working just fine if I allow it to load on the UI thread, but every time it loads a new image there is a major performance drop for a split second which I don't want. I have a lot of time to load the image in advance. It ultimately comes down to putting the following lines on a different thread:
BitmapImage BI = new BitmapImage();
BI.CacheOption = BitmapCacheOption.onload;
BI.BeginInit();
BI.UriSource = new Uri(ImagePath.ToString(), UriKind.RelativeOrAbsolute);
BI.EndInit();
//here is where I need to invoke functionality on the UI thread


then I need to somehow call the following lines of code on the UI thread:
Image myim = new Image();
myim.Source = BI;
PrimaryImageBrush = new BitmapCacheBrush(myim);
PrimaryRectangle.Fill = PrimaryImageBrush;
this.Visibility = Visibility.Visible;


I have tried all of the BitmapChaceOptions and they all cause the UI thread to run really slow, but the onload is the best by far, now if I can make it run in the background casually while giving priority to the UI thread it would by much smoother.
I have tried:
 
Dispatcher.BeginInvoke((Action)(() => {...}
Dispatcher.Invoke(() => {...}



Is there a way to return an object from a task? Or perhaps clone an object to a different thread/dispatcher? There has to be some way to communnicate between tasks/ threads with wpf. Currently it is the BitmapImage (BI) that was created on another thread that needs to be accessed on the UI thread Thank you in advance.

Is This A Good Question/Topic? 0
  • +

Replies To: wpf tasks/threading Objects from different threads

#2 tlhIn`toq   User is offline

  • Xamarin Cert. Dev.
  • member icon

Reputation: 6535
  • View blog
  • Posts: 14,450
  • Joined: 02-June 10

Re: wpf tasks/threading Objects from different threads

Posted 31 May 2016 - 02:48 PM

Why is all this in the C# code behind? This is my biggest concern: That you're doing so much of the UI stuff in code. That's generally a sign of not doing things in a WPF/MVVM way.
Normally you would bind the .Source in the XAML to a property in your ViewModel. Then you just change the view model property based on some criteria or another.
So let me ask you this, starting at the basics. Do you have ViewModel for this View?

I suspect the approach to the threading is off.
Normally I would have a ViewModel - then launch a thread to do some work, such as load the image from the HDD - or request it from a server via REST call - or whatever - returning the result from the thread back to the VM, setting a Image property to the result. Setting the property then updates the UI automatically through binding. See you set the image in the C# is a hint this is being done in a very WinForms way, rather than taking a WPF/MVVM approach. I'm worried you've swapped WPF for WinForms without applying any WPF concepts.
Was This Post Helpful? 1
  • +
  • -

#3 sk8ermeb   User is offline

  • D.I.C Head
  • member icon

Reputation: 20
  • View blog
  • Posts: 133
  • Joined: 23-March 10

Re: wpf tasks/threading Objects from different threads

Posted 31 May 2016 - 03:13 PM

Thank you tlhIn`toq, let me try what you said. I just finished getting through wpf4.5 unleashed. I must have missed the part on ViewModel can you point me in the right direction?

So I understand data binding and have implemented custom controls. I am finding it difficult to wrap my head around those concepts when it gets more complex. Does the callback for the DependencyPropery run in the UI thread? If so how can you spin off Loading of the BitmapImage in a task then use the results for the CachedBitmap when the dependent property is static? Sorry these may be stupid question but I can seem to figure this out.
Was This Post Helpful? 0
  • +
  • -

#4 sk8ermeb   User is offline

  • D.I.C Head
  • member icon

Reputation: 20
  • View blog
  • Posts: 133
  • Joined: 23-March 10

Re: wpf tasks/threading Objects from different threads

Posted 31 May 2016 - 04:18 PM

So I tried what you recommended (I think)
public static readonly DependencyProperty IsBufferedProperty = DependencyProperty.Register("IsBuffered", typeof(bool), typeof(MyControl), new PropertyMetadata(false, BufferedCallBack));
public bool IsBuffered
{
  get { return (bool)GetValue(IsBufferedProperty); }
  set { SetValue(IsBufferedProperty, value); }
}
public static void BufferedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
  MyControl rd = (MyControl)d;
  if (rd.IsBuffered)
    rd.LoadBufferIn(rd.PrimaryImagePath);
  else
    rd.ReleaseBuffer();
}
LoadBufferIn(MyControl mc)
{
...
}



And then from the other thread I am changing the property from the other thread
this.Dispatcher.BeginInvoke((Action)(() =>
{
   myrep.IsBuffered = true;
}));


It appears that doing this is running significantly slower than my previous implementation.
tlhIn`toq, if this is not what you meant please let me know. I need to set these properties from the code behind from another thread because of all the stuff the rest of my program does. Anywhere between 2 and 5 controls are created removed, set visible, set invisible in any second depending o manipulation events.
My whole goal is to make the UI run seamlessly while I do background tasks (such as loading images). So if any one knows how to communicate an object between threads or has insight into performing background tasks it would be very helpful. All I want to do is push 4 lines of code to another thread, and I feel like wpf should be capable of this I just cannot figure it out.
BitmapImage BI = new BitmapImage();
BI.CacheOption = BitmapCacheOption.onload;
BI.BeginInit();
BI.UriSource = new Uri(ImagePath.ToString(), UriKind.RelativeOrAbsolute);
BI.EndInit();


Thank you in advance
Was This Post Helpful? 0
  • +
  • -

#5 tlhIn`toq   User is offline

  • Xamarin Cert. Dev.
  • member icon

Reputation: 6535
  • View blog
  • Posts: 14,450
  • Joined: 02-June 10

Re: wpf tasks/threading Objects from different threads

Posted 01 June 2016 - 03:45 AM

View Postsk8ermeb, on 31 May 2016 - 04:13 PM, said:

Thank you tlhIn`toq, let me try what you said. I just finished getting through wpf4.5 unleashed. I must have missed the part on ViewModel can you point me in the right direction?

So I understand data binding and have implemented custom controls. I am finding it difficult to wrap my head around those concepts when it gets more complex. Does the callback for the DependencyPropery run in the UI thread? If so how can you spin off Loading of the BitmapImage in a task then use the results for the CachedBitmap when the dependent property is static? Sorry these may be stupid question but I can seem to figure this out.


4.5 unleashed by Sams covers databinding in Chapter 13. But they don't go into MVVM as a concept. In fact they don't use the term "ViewModel" anywhere in the book: At least a search I just did on the PDF didn't find it. Keep in mind this book was released in 2013, meaning it was written in 2012 - so its starting to show its age.
Flipping through the book I can't give it high marks. Any time I see someone coding directly against Button.Click I know there is a problem: Generally someone taking WinForm and mapping its concepts one-to-one to WPF.

Check my signature block: There are several links for WPF.
Google: "MVVM" - there are lots of tutorials, including right here on DIC

Keep in mind we're seeing only a tiny portion of your code, which generally is a good thing. In this case it makes it hard to tell how this code interacts with anything else. But even from this I think you have bigger issues in the overall architecture of your program. As a rule, if you've got Dispatcher.BeginInvoke - its probably wrong. There are places where its needed: But it tends to be one of those things that have a 1% legitimate need and 90% incorrect need - especially by new developers. It gets thrown in at the END of some chain of processes that weren't done right early on, in an attempt to strong arm something where the developer wants it.

I don't know why you have a CallBack in your control. Is there some external API making use of this?
Lines 10,11: I'm having trouble following your intention. If the image is buffered already then why are you loading it from a path?

When I was talking about property before, I meant a property for the Image. Load it once and hold on to it for the life of your View, or even the program if it is re-used often.

Quote

All I want to do is push 4 lines of code to another thread, and I feel like wpf should be capable of this I just cannot figure it out.

WPF can do it. You've already said you've done it but weren't happy with the speed results. So I'm under the impression the REAL goal is not about implementing those those - but instead to fix the architecture issues that are causing the horrible speed performance.

Let's stop saying the goal is to push the image from thread to thread. That's just bad and really isn't the goal. In more general terms, tell me what it is you're building, how you've laid it out, and what you're trying to do. Let's fix the problem at the earliest stages instead of trying to Band-Aide the result on the back end.
Was This Post Helpful? 1
  • +
  • -

#6 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 7135
  • View blog
  • Posts: 24,237
  • Joined: 05-May 12

Re: wpf tasks/threading Objects from different threads

Posted 01 June 2016 - 04:51 AM

If you read one of the other threads from our OP, you'll discover that the book is supposedly written by one if the software architects behind WPF. So either the book was ghostwritten, or the architect does not believe in MVVM, or sections of the book were written to demonstrate some concepts in the smallest possible code -- not necessarily the best written code.
Was This Post Helpful? 1
  • +
  • -

#7 sk8ermeb   User is offline

  • D.I.C Head
  • member icon

Reputation: 20
  • View blog
  • Posts: 133
  • Joined: 23-March 10

Re: wpf tasks/threading Objects from different threads

Posted 01 June 2016 - 09:18 AM

Quote

WPF can do it. You've already said you've done it but weren't happy with the speed results. So I'm under the impression the REAL goal is not about implementing those those - but instead to fix the architecture issues that are causing the horrible speed performance.

Sorry, what I meant was I already did it on the UI thread, but cannot figure out how to put these lines on another thread with the restriction that objects need to be created on the same thread. I suspect I am missing something but I havn't fond any examples on how to accomplish this. so of course when it loads the image on the UI thread there is a moment where the UI slows down. However you are right my overall goal is just to make it load the image without making the UI thread slower (not to push these lines to another thread). That's just the only way I can think of to make sure that loading the image does not affect UI performance.

Quote

Check my signature block: There are several links for WPF.
Google: "MVVM" - there are lots of tutorials, including right here on DIC

Thanks I am trying to learn everything I can. I think its the same book, mine is by Adam Nathan (the Microsoft architect published by Sams).

Quote

I don't know why you have a CallBack in your control. Is there some external API making use of this?
Lines 10,11: I'm having trouble following your intention. If the image is buffered already then why are you loading it from a path?

Before I post tons of code let me describe my overall program. I have a $300 tablet. In a use of this application there are between 1000 to 2000 controls that will be added. These being loaded are the result of touch events. Basically as your dragging your finger on a screen it generates new controls from a PostgreSQL server and preloads images from an FTP server URL then loads it into the application. This happens real time. What images than need to be loaded can't be predicted, these are provided to me be a stakeholder and can be changed on a minute by minute basis. But only maybe a dozen or so are on the screen at any one time. But all the controls must be pictures. Of course due to resource management the images themselves and their brushes are released when they go off the screen. I have done extensive hardware testing, and the best performance absolutely requires the control to be painted with a BitmapCacheBrush. This was the only way I could match the performance to direct X. I spent a week writing Direct X code side by side with WPF to match the performance. It didn't matter on my i7 solid state, but it did on whatever is in this $300 tablet.

Quote

When I was talking about property before, I meant a property for the Image. Load it once and hold on to it for the life of your View, or even the program if it is re-used often.


So the images can't be buffered when the window is created, because any number of controls could be created at any time. this combined with the sheer quantity of images and the minimal amount of resources requires me to do some resource management manually. The control does define a default image in case the image fails to load, I just drew a big red X in XML code. But as soon as that gets loaded it immediately makes the image invisible and loads the image in to a BitmapCacheBrush.
So the callback takes a path loads the image and creates a cached brush. MY custom Control is basically just a Rectangle with a few optimizations for performance and borders and shaders. On the UI thread only this is the code that works:
public BitmapCacheBrush PrimaryImageBrush;
LoadBufferIn()
{
  BitmapImage BI = new BitmapImage();
  BI.CacheOption = BitmapCacheOption.onload;
  BI.BeginInit();
  BI.UriSource = new Uri(ImagePath.ToString(), UriKind.RelativeOrAbsolute);
  BI.EndInit();
  Image myim = new Image();
  myim.Source = BI as BitmapImage;
  PrimaryImageBrush = new BitmapCacheBrush(img);
  PrimaryRectangle.Fill = PrimaryImageBrush;
  this.Visibility = Visibility.Visible;
}
public void ReleaseBuffer()
{
  this.Visibility = Visibility.Hidden;
  PrimaryImageBrush = null;            
}


I should note that when I use the term image, I am not using an image control because those are far to slow. I mean the image that I am loading from the hard drive that is added to a rectangle in the custom control via BitmapCacheBrush. It is more important to me to make the performance as fast pas possible rather then following convention.

Quote

There are places where its needed: But it tends to be one of those things that have a 1% legitimate need and 90% incorrect need - especially by new developers.

I wouldn't call myself a newer programmer, rather new to WPF. My background was originally embedded firmware and C and I am making my way up the abstraction ladder :). and so I will always choose performance over convention which is why I started this project with ShardDX, but after a previous thread with skydiver's help I was able to match the performance with WPF using BitmapCacheBrush and decided to move over.

But yes I want to do it right early on. I hope my description gives an idea of what I am trying to accomplish an I will start going through the resources you provided. Thank you very much for helping out!
Was This Post Helpful? 0
  • +
  • -

#8 sk8ermeb   User is offline

  • D.I.C Head
  • member icon

Reputation: 20
  • View blog
  • Posts: 133
  • Joined: 23-March 10

Re: wpf tasks/threading Objects from different threads

Posted 01 June 2016 - 09:39 AM

Quote

WPF can do it.

Also I would be very interested to see how WPF can do that. Everything I have read suggest that WPF is incapable of moving those 4 lines of code to a thread other than the UI. Not that I will go with that but the fact that I don't know how to do something that simple proves there are some major threading concepts of WPF I still don't understand and cant seem to figure out, and that explanation would help me tremendously. I would give you 10 thumbs up for that if I could :) haha
Was This Post Helpful? 0
  • +
  • -

#9 tlhIn`toq   User is offline

  • Xamarin Cert. Dev.
  • member icon

Reputation: 6535
  • View blog
  • Posts: 14,450
  • Joined: 02-June 10

Re: wpf tasks/threading Objects from different threads

Posted 01 June 2016 - 05:02 PM

Quote

In a use of this application there are between 1000 to 2000 controls that will be added.
...
But only maybe a dozen or so are on the screen at any one time.


If you're making 1000-2000 controls up front for something that only shows one to two dozen at a time then there is a serious design flaw here.

Quote

My background was originally embedded firmware and C and I am making my way up the abstraction ladder

I think that's great. I also suspect it is the root of the issue. I suspect the design is probably still very old-school. Time and time again I see a huge disconnect with new WPF developers between the storing of data, and the display of UI. So often people want to make controls for everything. In reality we just don't do that. You really only need have the data... then display it as needed... making the controls for displaying it when you actually have to display.

ControlTemplates and DataTemplates often are the key to this.

Let me dummy up an example:

If you have an address book for your company it might have 10,000 records.
You don't make 10,000 AddressBookControl controls.
You use a ListView or some other control designed to show collections of like objects, and you make a XAML data template that shows them how you want them.
It might grab the contact's photo to show on the control... the phone number... a button to dial via Skype... etc.

When the ListView is shown it looks like a page in a person's DayRunner, or the YellowPages page, or the Outlook Contacts page... All of those are really just ListView controls with fancy ControlTemplate and DataTemplate and Styles created.

I've done this with 100,000 song objects for radio stations and had real-time play position, animation, font styles and so on, all in WPF all with amazing response. It really does work. But you have to realize you are only storing data object 99% of the time - and letting the XAML handle the presentation at the time of presentation and not before.

I know this is very general- and probably a bit disheartening - and doesn't directly say "change these three lines here". Sorry about that. Nobody wants to hear "I'm 95% certain its a case of 1990's design in a 2016 paradigm." - but I really think that's the case.

UPDATE: Check you private messages
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1