Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# Threading User-controls , +
Dear All,
I am working on a designing application in which i need to apply threading since one section displays list of all the images of the folder which on high count hangs the UI. so i am using threading to solve this problem.
 
I have a custom made control(inheriting FlowLayoutPanel) which displays the images selected from a folder in size of 100 x 100(say). I need to display these images using multi-threading.
 
Custom Control Class:-
public partial class DesignListView : FlowLayoutPanel
    {
        public DesignListView()
        {
            InitializeComponent();
        }
        private List<String> fileList;
        public List<String> FileList
        {
            get
            {
                return this.fileList;
            }
            set
            {
                this.fileList = value;
                PopulateThumbnailInThread();
            }
        }
        public void PopulateThumbnailInThread()
        {
            Thread t = new Thread(new ThreadStart(PopulateThumbnails));
            t.IsBackground = true;
            t.Start();
        }
        public void PopulateThumbnails()
        {
            this.SuspendLayout();
            this.Controls.Clear();
            this.ResumeLayout();
            if (fileList == null)
                return;
            for (int i = 0; i < fileList.Count; ++i)
            {
                ThumbnailDisplayControl tdc = new ThumbnailDisplayControl(fileList[i]);
                tdc.MouseDown += new MouseEventHandler(tdc_MouseDown);
                AddControl(tdc);
            }
        }
        public delegate void AControl(ThumbnailDisplayControl tdc);
        public void AddControl(ThumbnailDisplayControl tdc)
        {
            if (tdc.InvokeRequired)
            {
                tdc.BeginInvoke(new AControl(AddControl), new object[] { tdc });
                return;
            }
                this.Controls.Add(tdc);
        }
        void tdc_MouseDown(object sender, MouseEventArgs e)
        {
            //Displays the selected design
        }
        
        public event DesignSelectedEventHandler DesignSelected;
        protected virtual void OnDesignSelected(DesignSelectedEventArgs e)
        {
            if (DesignSelected != null)
                DesignSelected(this, e);
        }
        
    }
    public class ThumbnailDisplayControl : PictureBox
    {
        // provides image with design and its name.
    }
    public class DesignSelectedEventArgs : EventArgs
    {
        // delegate properties n stuffs
    }
    public delegate void DesignSelectedEventHandler(object sender, DesignSelectedEventArgs e);
 
Currently i am having problem :
Cross-thread operation not valid: Control 'designListView1' accessed from a thread other than the thread it was created on.
 
Need to Know:-
. Can i call the thread [PopulateThumbnailInThread()] in this class or should i call the thread in Main Class
. Can anyone suggest what should i do?
 
Any Help will be appreciated.
Posted 14-Jul-11 21:04pm
Edited 14-Jul-11 21:35pm
v4
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

You don't need to add any thread-safe features in the custom controls. Anyway, a non-UI thread cannot call any UI methods or properties. Working with UI from the non-UI thread is nevertheless possible, but the calls are dispatched to the UI thread using inter-thread invocation feature.
 
Instead of direct calls, 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
  Permalink  
Comments
SAKryukov at 15-Jul-11 3:02am
   
OP commented:
 
Thankyou for suggestion. i was waiting for a suggestion which will set me moving.
SAKryukov at 15-Jul-11 3:05am
   
First, please don't post non-solutions via "Add your solution here". Use "Improve question", "Add comment", reply to comment.
 
This is not even a suggestion -- this is a regular way to use UI from a non-UI thread.
If you see it makes sense please formally accept the answer (green button) -- thanks.
--SA
johannesnestler at 15-Jul-11 5:28am
   
You are so brave. Answering this kind of question 1000 times. Good that you can refer to your past answers :-). Thank you for your efford on CP!
SAKryukov at 15-Jul-11 5:47am
   
Thank you. What else can I do?
--SA
le.Festin at 15-Jul-11 6:19am
   
I added multithreading in my application but the GUI still hangs.
 
My DesignListView (Class):
private List fileList;
public List FileList
{
get
{
return this.fileList;
}
set
{
this.fileList = value;
PopulateThumbnails();
}
}
 
public void PopulateThumbnails()
{
if (fileList == null)
return;
 
for (int i = 0; i < fileList.Count; ++i)
{
Thread t = new Thread(new ThreadStart(AddControl));
t.IsBackground = true;
t.Start();
}
}

private int cnt = 0;
 
public delegate void AControl();
public void AddControl()
{
if (this.InvokeRequired)
{
InvokeCount++;
this.BeginInvoke(new AControl(AddControl));
return;
}
lock (this)
{
if (cnt >= fileList.Count)
return;
 
ThumbnailDisplayControl tdc = new ThumbnailDisplayControl(fileList[cnt]);

tdc.MouseDown += new MouseEventHandler(tdc_MouseDown);
this.Controls.Add(tdc);
cnt++;
}
}
 
I know the code style is not good but i just wanted to know if that would stop GUI hang but it didnot.
 
Is my class is taking time to update itself. I am not able to point out where i went wrong.
 
Please help.
SAKryukov at 19-Jul-11 0:35am
   
Of course. Look what are you doing! You create a thread which makes no sense. It does not do anything a thread should do. There is no actions independent of UI. Moreover, it invokes itself! (Wow! what a fantasy!). Look at "this.BeginInvoke(new AControl(AddControl));" -- this is a part of the method "AddControl". The thread hands itself! Wow! Where is the exception handler on top of each thread?
Outrageous! How did you even invent it all.
 
OK, what's the purpose of this code?
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

I recommend that you don't create one control per file. That seems unnecessary, the list can manage all the entries and painting itself, which will save you a lot of window handles and time/memory used in creating controls. You should not need to do the display in a separate thread, it should not be that slow.
 
You can see how to make a list-like user control (in WinForms) in my article here: LineEditor Control – Line based visual input/output[^].
 
Also, is there a reason you can't just use the ListView for this? What you are trying to do (a list with items and images) sounds very similar to what the ListView will do.
 
As for the specific question you asked, refer to SA's solution.
  Permalink  
Comments
johannesnestler at 15-Jul-11 5:23am
   
I agree with your points. OP should think about his design first. This is allways a good habit if you run into performance problems.
le.Festin at 15-Jul-11 5:49am
   
Dear BobJanova,
 
According to my calculation the average time taken for a single picture from my ThumbnailDisplayControl class takes about .7 sec.So, for many pictures it will take a lot of time which will hang the UI, so i should use threading.
 
And ty for the ListView Idea. I really have no idea why i didnot this of this one.
BobJanova at 15-Jul-11 13:40pm
   
A single image should take nowhere near 700ms to render. Are you generating it dynamically each time, or resizing it from a much larger image each time? If so, you should cache the display form within the control.
le.Festin at 15-Jul-11 5:53am
   
but i guess i will be sticking with my own class for the moment. By the way, ty for your idea. I will surely be using ListView on my next code

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

  Print Answers RSS
0 OriginalGriff 515
1 Maciej Los 349
2 Richard MacCutchan 220
3 BillWoodruff 209
4 Mathew Soji 160
0 OriginalGriff 8,654
1 Sergey Alexandrovich Kryukov 7,407
2 DamithSL 5,639
3 Maciej Los 5,229
4 Manas Bhardwaj 4,986


Advertise | Privacy | Mobile
Web03 | 2.8.1411023.1 | Last Updated 15 Jul 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100