Click here to Skip to main content
15,881,852 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
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:-
C#
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
Updated 14-Jul-11 20:35pm
v4

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
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 15-Jul-11 3:02am    
OP commented:

Thankyou for suggestion. i was waiting for a suggestion which will set me moving.
Sergey Alexandrovich Kryukov 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 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!
Sergey Alexandrovich Kryukov 15-Jul-11 5:47am    
Thank you. What else can I do?
--SA
le.Festin 15-Jul-11 6:19am    
I added multithreading in my application but the GUI still hangs.

My DesignListView (Class):
private List<string> fileList;
public List<string> 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.
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.
 
Share this answer
 
Comments
johannesnestler 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 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 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 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)



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