Loading...


bookmark - Help Needed @ C#: Cross-thread Operation Not Valid

Help Needed @ C#: Cross-thread Operation Not Valid

 
 Discussion by turbopowerdmaxsteel with 5 Replies.
 Last Update: July 13, 2009, 5:10 pm
 
bookmark - Help Needed @ C#: Cross-thread Operation Not Valid  
Quickly Post to Help Needed @ C#: Cross-thread Operation Not Valid  w/o signup Share Info about Help Needed @ C#: Cross-thread Operation Not Valid  using Facebook, Twitter etc. email your friend about Help Needed @ C#: Cross-thread Operation Not Valid Print
Reply / Comment New Discussion / Topic Share / Bookmark E-Mail a Friend Print

I have a class named as test which triggers an event using the Timer class, the code for which is given below.

CODE

using System;
using System.Timers;

namespace Test
{
class test
{
public delegate void TestEventHandler();
public event TestEventHandler TestEvent;

protected Timer TestTimer = new Timer();

public test()
{
TestTimer.Elapsed += new ElapsedEventHandler(Tick);
TestTimer.Interval = 1000;
}

private void Tick(object source, ElapsedEventArgs e)
{

TestEvent();
}

public void Go()
{
TestTimer.Enabled = true;
}
}
}



The problem that I am facing with, is that the Event runs in a seperate thread and doesn't allow any kind of operation on the Form's controls. The code for the form is given below.

CODE

using System;
using System.Windows.Forms;

namespace Test
{
public partial class Form1 : Form
{
test A = new test();
public Form1()
{
InitializeComponent();
A.TestEvent += new test.TestEventHandler(A_TestEvent);
}

void A_TestEvent()
{
this.Text = "Test Text"; // This is where the Exception "Cross Threaded Operation not valid" is generated
}


private void Form1_Load(object sender, EventArgs e)
{
A.Go();
}
}
}

How do I invoke the event in the same thread as that of the form's?

   Thu Feb 22, 2007    Reply         

It's a new design change either with VS2005 or with the .NET Framework 2.0 to eliminate alot of concurrency bugs. When the exception handler pops up in VS, click the "more info" link...it will take you to an MSDN article explaining how to properly use delegates to do what you want to do in a thread-safe manner.

   Fri Mar 9, 2007    Reply         

Cross Thread Operations
Help Needed @ C#: Cross-thread Operation Not Valid

Yes , you cannot access a windows forms control or a windows forms component from a different thread. What you need to do in order to access the form controls is to invoke the control using a delegate with the help of control.BeginInvoke(). I have posted an article on the issue with sample code on my blog at http://asadsiddiqi.Wordpress.Com/2007/12/24/responsive-user-interfaces-with-ui-threads/
Hope this helps .

Thanks

-reply by Muhammad Asad Siddiqi







   Sun Apr 6, 2008    Reply         


I have forgotten how the whole sample did.
Just remember that you have to use
Control.InvokeRequired to check that
if you are not on the right thread.

If so, skill to the next method call and try
to update the control UI.

Wish this help

Eric

   Sun Jun 15, 2008    Reply         

Here I am posting the full solution to my own problem. Maybe this will help out some beginners. And no, it didn't take me a year and a half to figure this one out, thanks to MSDN. Its just that I didn't bother to look into this once I had the answer. Anyways, here goes it.

As said by Muhammad, the trick is in using the Control.BeginInvoke (or Control.Invoke) method to force the method to be executed in the same thread as that of the control. The difference between Invoke and BeginInvoke is that the former is synchronous while the latter is asynchronous. Using BeginInvoke makes more sense as the whole idea is to create efficient multi-threaded application. BeginInvoke starts a new thread passing along a delegate object of the method to be invoked and the parameters to be passed to it.

In this case, the BeginInvoke method of the owner Form has to be called from the test class. So, we include an ISynchronizeInvoke parameter in the constructor of the class which is then stored in a member variable. The ISynchronizeInvoke Interface must be implemented in-order to execute a delegate asynchronously. Thankfully, this has been done in the System.Windows.Forms.Control class, so it doesn't require any work on our part.

CODE

protected ISynchronizeInvoke SyncObject;

public test(ISynchronizeInvoke SyncObject)
{
this.SyncObject = SyncObject;
TestTimer.Elapsed += new ElapsedEventHandler(Tick);
TestTimer.Interval = 1000;
}


We add a new delegate with the same signature as that of the method Tick (the event handler for the System.Timers.Timer's elapsed event).

CODE

protected delegate void TickDelegate(object source, ElapsedEventArgs e);


The Tick method makes sure that it is running in the same thread as that of the Synchronizing object passed to the class's constructor using the Control.InvokeRequired property. If it is not, it calls the BeginInvoke method of the SyncObject passing along a delegate to itself and an object array of it's parameters. No further work is done in this call to the Tick method. After a while, the Tick method is invoked again, only this time on the owner form's thread. The InvokeRequired property returns false and the actual work of the method is done.

CODE

private void Tick(object source, ElapsedEventArgs e)
{
if (SyncObject.InvokeRequired)
SyncObject.BeginInvoke(new TickDelegate(Tick), new object[] { source, e });
else
TestEvent();
}


Only one change needs to be made in the Form class - a reference to itself must be passed to the contstructor of the test class. For this, the instantiation of the object is now done inside the constructor (this keyword is only valid inside a non-static property, method, or constructor).

CODE

test A;
public Form1()
{
InitializeComponent();
A = new test(this);
A.TestEvent += new test.TestEventHandler(A_TestEvent);
}


Full code for the two classes:-

Test class

CODE

using System;
using System.Timers;
using System.ComponentModel;

namespace Test
{
class test
{
public delegate void TestEventHandler();
public event TestEventHandler TestEvent;

protected Timer TestTimer = new Timer();
protected ISynchronizeInvoke SyncObject;

public test(ISynchronizeInvoke SyncObject)
{
this.SyncObject = SyncObject;
TestTimer.Elapsed += new ElapsedEventHandler(Tick);
TestTimer.Interval = 1000;
}

protected delegate void TickDelegate(object source, ElapsedEventArgs e);
private void Tick(object source, ElapsedEventArgs e)
{
if (SyncObject.InvokeRequired)
SyncObject.BeginInvoke(new TickDelegate(Tick), new object[] { source, e });
else
TestEvent();
}

public void Go()
{
TestTimer.Enabled = true;
}
}
}


Form Class

CODE

using System;
using System.Windows.Forms;

namespace Test
{
public partial class Form1 : Form
{
test A;
public Form1()
{
InitializeComponent();
A = new test(this);
A.TestEvent += new test.TestEventHandler(A_TestEvent);
}

void A_TestEvent()
{
this.Text = "Test Text"; // This is where the Exception "Cross Threaded Operation not valid" used to be generated
}


private void Form1_Load(object sender, EventArgs e)
{
A.Go();
}
}
}

   Sat Jun 21, 2008    Reply         

Another wayHelp Needed @ C#: Cross-thread Operation Not Valid

Hi all!

Just wondering why you wouldnt just use the timer thats found in the System.Windows.Forms.Timer class? The difference is that this "Forms" timer is always calling the Tick event handler on the same thread as the UI. So it seems to be an easier solution to your problem above. However, your solution is still valid when its not the UI thread you are trying to execute commands on. :-)

Kyryll 

-reply by Kyryll

   Mon Jul 13, 2009    Reply         


Quickly Post to Help Needed @ C#: Cross-thread Operation Not Valid  w/o signup Share Info about Help Needed @ C#: Cross-thread Operation Not Valid  using Facebook, Twitter etc. email your friend about Help Needed @ C#: Cross-thread Operation Not Valid Print
Reply / Comment New Discussion / Topic Share / Bookmark E-Mail a Friend Print

Similar Topics:

Multithreaded Listview Control In D...

I maybe crossing into the advanced questions on this one but I have been working on this problem for a little over a week now and I am just plain stuck. I have a windows application in VB.NET. The main form has a listview with approx 15 items and five subitems in each item. The list v ...more

   23-Feb-2006    Reply         

Help Multi threading Trouble In Cu...

I am creating a wrapper component for the System.Net.Sockets.Socket class which would resemble the Winsock control. The basic idea is to do operations such as Connect & Receive asynchronously. The component has events such as Connected, PacketArrival in response to these. To do this, I us ...more

   15-Aug-2007    Reply         

Vb.net How To Trap Exceptions In I...

I am having some trouble in trapping the exceptions raised by Invoked methods. By Invoked, I mean the methods that have been Invoked by the Control.Invoke method. Given below is a simple example of this problem. I have a Form named Form1 which contains an object Tim ...more

   15-Nov-2007    Reply         

Mono On Gentoo    Mono On Gentoo (0) (2) Interesting Directsound Capture Device Issue   Interesting Directsound Capture Device Issue