Friday, July 20, 2007

Cross thread operation failure , Use Invoke, BeginInvoke fn...

Cross thread operation failure :

In Visual studio 2005, if we are accessing the control within a form, at run time we will get
Cross thread operation failure.

.NET runtime checks whether the control is used in the thread which created the control. if it is used within the thread at which the control is created, then it will allows execution.
otherwise the .NET runtime will throws an exception.

in the following example if we are creating the thread within that thread if we try to add data to the listbox. .NET runtime will throws exception at
runtime.


For Cross thread operation, we have to call the Invoke() or BeginInvoke() fn to update the control.

Invoke() and BeginInvoke() fns are thread safe. all other threads are not thread safe. the user has to make it as thread safe.

within Thread function, we called the

listBox1.BeginInvoke(m_UpdateList, "sundar");

which inturn updates the listbox. BeginInvoke() or Invoke() blocks the thread until it updates the data to the control.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;


namespace CrossThread
{
public partial class Form1 : Form
{
private Thread thread1 = null;
private ThreadStart threadStart1 = null;

public delegate void UpdateList(string text);
public UpdateList m_UpdateList = null;



public Form1()
{
InitializeComponent();
m_UpdateList += new UpdateList(SetToList1);
threadStart1 = new ThreadStart(AddToList1);
thread1 = new Thread(threadStart1);

}


public void SetToList1(string text)
{
listBox1.Items.Add(text);
}


private void AddToList1()
{
try
{
int i = 10;
while (true)
{
if (i <= 0) break;
listBox1.BeginInvoke(m_UpdateList, "sundar");
i--;
Thread.Sleep(1000);
}

}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());

}
}

private void btnStart_Click(object sender, EventArgs e)
{

try
{
thread1.Start();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}

}

private void btnStop_Click(object sender, EventArgs e)
{
thread1.Abort();
}
}
}



Use of Invoke() fn >>>

Every control has the following members:

InvokeRequired (boolean field)
Invoke() fn


InvokeRequired field is true if the cross thread operation takes place otherwise it will be false.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace CrossThreadInvoke
{
public partial class Form1 : Form
{

private Thread thread1 = null;
private ThreadStart threadStart1 = null;
delegate void UpdateControl (string text);
event UpdateControl m_UpdateControl = null;



public Form1()
{
InitializeComponent();
threadStart1 = new ThreadStart(ThreadProcedure);
thread1 = new Thread(threadStart1);
m_UpdateControl = new UpdateControl(UpdateList);

}
private void UpdateList(string text)
{
if (listBox1.InvokeRequired)
{
listBox1.Invoke(m_UpdateControl, text);
}
else
{
listBox1.Items.Add(text);
}
}

private void ThreadProcedure()
{
int i = 0;
while (true)
{
if (i > 10)
{
break;
}

m_UpdateControl("Sundar");
i++;
}
thread1.Abort();
}
private void btnStart_Click(object sender, EventArgs e)
{
thread1.Start();
}

private void btnStop_Click(object sender, EventArgs e)
{
thread1.Abort();
}
}
}

Labels: , ,

Difference between Delegate and Delegate With event

Is there any difference between the delegate and delegate with event ?...

Yes... See the sample



delegate void UpdateControl( string text);
UpdateControl m_UpdateControl = null;
private event UpdateControl m_EventUpdateControl = null;


m_UpdateControl += new UpdateControl( UpdateListCtrl);
m_EventUpdateControl += new UpdateControl( UpdateListCtrl);

private void UpdateListCtrl()
{
listSent.items.Add("Test" + listSent.items.count);
}




we can create the object as follows :

m_UpdateControl = new UpdateControl(UpdateListCtrl); // will work properly

But the following code will not work properly...

m_EventUpdateControl = new UpdateControl(UpdateListCtrl);

we have to change it as

m_EventUpdateControl += new UpdateControl(UpdateListCtrl);

This implies...
we can set the delegate object as null as follows in anywhere like during initialization or within any fn.


m_UpdateControl = null;


But for Event with delegate object, we will not be able to initialize it as null , it affects the other client's delegates also.

m_EventUpdateControl = null; // Exception : we can initialize null for the event with delegate object during initialization.


what it means is that if we use the event keyword no client class can set it to null. This is very important. Multiple clients can use the same delegate. After multiple client have added a function to listen to the callback of the delegate. But now one of the client sets the delegate to null or uses the = sign to add a new call back. This means that the previous invocation list will not be used any more. Hence all the previous client will not get any of the callback even if they have registered for the call back.

Hence we can say that the even keyword adds a layer of protection on the instance of the delegate. The protection prevents

any client to reset the delegate invocation list. They can only add or remove the target from the invocation list.

Labels: , ,