8 Replies - 3123 Views - Last Post: 11 January 2010 - 01:57 AM Rate Topic: -----

#1 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1641
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Cross thread error [RESOLVED]

Posted 10 January 2010 - 11:44 AM

I know what's causing this, and I know where it's happening but I dont know how to resolve it. I have an Extension Method for handling the Invoke that looks like this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace XPUtilitiesPro.Core
{
	public static class SynchronizeInvoke
	{
		public static void CustomInvoke<T>(this T @control, Action<T> toPerform) where T : ISynchronizeInvoke
		{
			if (@control.InvokeRequired)
				@control.Invoke(toPerform, new object[] { @control });
			else
				toPerform(@control);
		}
	}
}



And when creating PictureBoxes at runtime and adding them to a Panel I use it like so

private void LoadWallpapers(Panel p, string folder)
{
	progressBar1.CustomInvoke(p1 => p1.Visible = true);
	progressBar1.CustomInvoke(p1 => p1.Enabled = true);

	p.Controls.Clear();
	int position = 0;
	int count = 10;
	string[] validExtensions = new string[] { ".jpg", ".bmp", ".gif", ".png" };
	DirectoryInfo info = new DirectoryInfo(folder);

	foreach (FileInfo f in info.GetFiles())
	{
		for (int i = 0; i < validExtensions.Length; i++)
		{
			if (f.Extension.ToString().ToLower() == validExtensions[i].ToLower())
			{
				PictureBox pb = new PictureBox();
				pb.CustomInvoke(pic => pic.Name = "WallpaperPB" + count);
				pb.CustomInvoke(pic => pic.Cursor = Cursors.Hand);
				pb.CustomInvoke(pic => pic.Parent = p);
				pb.CustomInvoke(pic => pic.Size = new Size(130, 98));
				pb.CustomInvoke(pic => pic.SizeMode = PictureBoxSizeMode.StretchImage);
				pb.CustomInvoke(pic => pic.Location = new Point(position + 10, 20));
				pb.CustomInvoke(pic => pic.Image = Image.FromFile(f.FullName));
				pb.CustomInvoke(pic => pic.Image.Tag = f.FullName);
				pb.CustomInvoke(pic => pic.MouseHover += new EventHandler(pb_MouseHover));
				pb.CustomInvoke(pic => pic.MouseLeave += new EventHandler(pb_MouseLeave));
				pb.CustomInvoke(pic => pic.Click += new EventHandler(pb_Click));
				position += 135;
				count += 1;
			}
		}
	}

	label1.CustomInvoke(l=> l.Text = string.Format("Current Directory: {0}", folder));

	progressBar1.CustomInvoke(p1 => p1.Visible = false);
	progressBar1.CustomInvoke(p1 => p1.Enabled = false);
}



The invoke extension I use works because I use it on about 20 custom Panel controls in this application. The line that's giving the error is here

pb.CustomInvoke(pic => pic.Parent = p);



Anyone have any ideas on how I can execute this line without getting the cross-thread error?

Is This A Good Question/Topic? 0
  • +

Replies To: Cross thread error [RESOLVED]

#2 FlashM  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 382
  • View blog
  • Posts: 1,195
  • Joined: 03-December 09

Re: Cross thread error [RESOLVED]

Posted 10 January 2010 - 11:55 AM

Your picturebox is in your main thread while your LoadWallpapers method runs in a different thread? I never used invocation as an extension method, but will certainly take a look and if I manage to resolve it, I'll give you a post.
Was This Post Helpful? 0
  • +
  • -

#3 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1641
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Re: Cross thread error [RESOLVED]

Posted 10 January 2010 - 12:07 PM

Oh I know that. I use this extension method in about 20 other custom Panels and it works beautifully. This one instance (one line of code) is the only error I've ran into when using it. I cannot understand why everything else works except when trying to set it's Parent
Was This Post Helpful? 0
  • +
  • -

#4 FlashM  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 382
  • View blog
  • Posts: 1,195
  • Joined: 03-December 09

Re: Cross thread error [RESOLVED]

Posted 10 January 2010 - 12:13 PM

I agree, it's really weird...
Was This Post Helpful? 0
  • +
  • -

#5 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1641
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Re: Cross thread error [RESOLVED]

Posted 10 January 2010 - 01:13 PM

I forgot to mention. I am doing it this way because the image thumbnails are being loaded with a BackgroundWorker for efficiency and to prevent the UI from locking up (that's why I'm using Invoke and getting a cross-thread communication error)
Was This Post Helpful? 0
  • +
  • -

#6 FlashM  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 382
  • View blog
  • Posts: 1,195
  • Joined: 03-December 09

Re: Cross thread error [RESOLVED]

Posted 10 January 2010 - 03:31 PM

PsychoCoder, I managed to reproduce the same error that you were encountering and here's what I think...
Your LoadWallpapers method runs in a worker thread. This worker thread is the one that creates an instance of a PictureBox.
When you are calling methods like:

pb.CustomInvoke(pic => pic.Name = "WallpaperPB" + count);
pb.CustomInvoke(pic => pic.Cursor = Cursors.Hand);
pb.CustomInvoke(pic => pic.Size = new Size(130, 98));

etc...

this error is not thrown, since you are calling properties of a picture box in the same thread that created this picture box.

but when you try to assign a parent, you are calling the control's properties (Panel's properties) that are on a different thread and that's why your error is thrown.

I made a quick sample code that works and I hope this explains your problem.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.IO;

namespace PanelsApp
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void LoadImages(object stateInfo)
		{
			object[] obj = (object[])stateInfo;
			Panel pnl = obj[0] as Panel;
			string folder = obj[1] as string;
			int position = 0;
			int count = 10;

			DirectoryInfo info = new DirectoryInfo(folder);
			foreach (FileInfo file in info.GetFiles())
			{
				PictureBox pb = new PictureBox();
				pb.Name = "WallpaperPB" + count;
				pb.Cursor = Cursors.Hand;
				pb.Size = new Size(130, 98);
				pb.SizeMode = PictureBoxSizeMode.StretchImage;
				pb.Location = new Point(position + 10, 20);
				pb.Image = Image.FromFile(file.FullName);
				pb.Image.Tag = file.FullName;
				SetParent(pnl, pb);
				//pb.Parent = pnl; //This produces the cross thread illegal operation

				position += 135;
				count += 1;
			}
		}

		public delegate void SetParentDelegate(Control parent, Control child);
		private void SetParent(Control parent, Control child)
		{
			if (parent.InvokeRequired)
			{
				parent.Invoke(new SetParentDelegate(SetParent), parent, child);
			}
			else
			{
				child.Parent = parent;
			}
		}

		private void button1_Click(object sender, EventArgs e)
		{
			string folder = @"C:\Images";

			Thread t = new Thread(new ParameterizedThreadStart(LoadImages));
			t.IsBackground = true;
			t.Start(new object[] { pnlImages, folder });
		}
	}
}


This post has been edited by FlashM: 10 January 2010 - 03:33 PM

Was This Post Helpful? 1
  • +
  • -

#7 FlashM  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 382
  • View blog
  • Posts: 1,195
  • Joined: 03-December 09

Re: Cross thread error [RESOLVED]

Posted 10 January 2010 - 04:37 PM

Another way would be to call this method:

pb.CustomInvoke(pic => pic.Name = "WallpaperPB" + count);
pb.CustomInvoke(pic => pic.Cursor = Cursors.Hand);
pb.CustomInvoke(pic => pic.Size = new Size(130, 98));
Invoke(new MethodInvoker(delegate() { pb.Parent = pnl; }));
...

This post has been edited by FlashM: 10 January 2010 - 04:44 PM

Was This Post Helpful? 0
  • +
  • -

#8 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1641
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Re: Cross thread error [RESOLVED]

Posted 10 January 2010 - 07:47 PM

Wow, how could I be so blind. See what happens when you write code while fighting a migraine (Not that I would have found it anyways). Thanks a lot man, saved me a lot of trouble :)
Was This Post Helpful? 0
  • +
  • -

#9 FlashM  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 382
  • View blog
  • Posts: 1,195
  • Joined: 03-December 09

Re: Cross thread error [RESOLVED]

Posted 11 January 2010 - 01:57 AM

No problem, man, anytime... Happy coding :-)

This post has been edited by FlashM: 11 January 2010 - 01:57 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1