|
-
March 9th, 2010, 02:47 AM
#1
Sharing data between threads
hi All,
I am new to c#. I have two threads in my application. One thread (UI thread) takes inputs from user and another thread (worker thread) does some calculation. Now if user clicks stop then worker thread should stop or exit from where it was. But I do not know how to do this in C#. I tried it using static property but no results. If some how I can modify a variable of a class from UI thread and it can be checked in worker thread. Please suggest a way by which I can communicate between 2 threads.
-
March 9th, 2010, 04:42 AM
#2
Re: Sharing data between threads
I suggest using the BackGroundWorker class, which supports a cancellation feature
It's not a bug, it's a feature!
-
March 9th, 2010, 07:12 AM
#3
Re: Sharing data between threads
well, I worked with a global variable...not static one
here this is a network snifer works in a working thread while countinuing variable is true...once I click the stop the variable gets false and the working thread stops...
Code:
private void button2_Click(object sender, EventArgs e)
{
if (continuing)
{
continuing = false;
button2.Text = "Start";
}
else
{
continuing = true;
button2.Text = "Stop";
}
//IPEndPoint ip = new IPEndPoint(IPAddress.Parse("10.233.125.159"), 80);
//Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//sock.Bind(ip);
////sock.Connect(ip);
//sock.Listen(2);
////sock.Blocking = false;
//richTextBox1.Text += sock.SendBufferSize.ToString();
//richTextBox1.Text += sock.ReceiveBufferSize.ToString();
////Socket ou = sock.Accept();
////richTextBox1.Text += string.Format("{0}", ou.LocalEndPoint.AddressFamily.ToString()+ou.ReceiveBufferSize.ToString()+ou.SendBufferSize.ToString());
////ou.Close();
//sock.Close();
if (continuing)
{
string ip1 = @"192.168.0.8";
socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
byte[] buffer = new byte[2048];
//SocketPair socketpair = new SocketPair(socket, buffer);
//socket.Blocking = true;
socket.Bind(new IPEndPoint(IPAddress.Parse(ip1), 80));
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
byte[] IN = new byte[4] { 1, 0, 0, 0 };
byte[] OUT = new byte[4];
int ret_code = socket.IOControl(IOControlCode.ReceiveAll, IN, OUT);
ret_code = OUT[0] + OUT[1] + OUT[2] + OUT[3];
//if (ret_code != 0)
// ret_val = false;
socket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(Onreceive), null);
//IPEndPoint h = (IPEndPoint)socket.LocalEndPoint;
//IPEndPoint h1 = (IPEndPoint)socket.RemoteEndPoint;
//richTextBox1.Text += h.Address.ToString() + "..."+h.Port;
//richTextBox1.Text += h1.Address.Address.ToString();
}
}
IPHeader ipHeader;
TCPHeader tcpHeader;
private void Onreceive(IAsyncResult ar)
{
int nReceived = socket.EndReceive(ar);
ipHeader = new IPHeader(byteData, nReceived);
switch (ipHeader.ProtocolType)
{
case Protocol.TCP:
tcpHeader = new TCPHeader(ipHeader.Data, //IPHeader.Data stores the data being
//carried by the IP datagram
ipHeader.MessageLength);//Length of the data field
//richTextBox1.Text += ipHeader.DestinationAddress.ToString() + " " + tcpHeader.DestinationPort+Environment.NewLine;
richTextBox1.BeginInvoke(new MethodInvoker(UpdateText));
//If the port is equal to 53 then the underlying protocol is DNS
//Note: DNS can use either TCP or UDP thats why the check is done twice
//if (tcpHeader.DestinationPort == "53" || tcpHeader.SourcePort == "53")
//{
// TreeNode dnsNode = MakeDNSTreeNode(tcpHeader.Data, (int)tcpHeader.MessageLength);
// rootNode.Nodes.Add(dnsNode);
//}
break;
case Protocol.UDP:
//UDPHeader udpHeader = new UDPHeader(ipHeader.Data, //IPHeader.Data stores the data being
// //carried by the IP datagram
// (int)ipHeader.MessageLength);//Length of the data field
//TreeNode udpNode = MakeUDPTreeNode(udpHeader);
//rootNode.Nodes.Add(udpNode);
////If the port is equal to 53 then the underlying protocol is DNS
////Note: DNS can use either TCP or UDP thats why the check is done twice
//if (udpHeader.DestinationPort == "53" || udpHeader.SourcePort == "53")
//{
// TreeNode dnsNode = MakeDNSTreeNode(udpHeader.Data,
// //Length of UDP header is always eight bytes so we subtract that out of the total
// //length to find the length of the data
// Convert.ToInt32(udpHeader.Length) - 8);
// rootNode.Nodes.Add(dnsNode);
//}
break;
case Protocol.Unknown:
break;
}
if (continuing)
{
byteData = new byte[4096];
//Another call to BeginReceive so that we continue to receive the incoming
//packets
socket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None,
new AsyncCallback(Onreceive), null);
}
}
private void UpdateText()
{
richTextBox1.Text += ipHeader.DestinationAddress.ToString() + " " + tcpHeader.SourcePort + Environment.NewLine;
}
-
March 9th, 2010, 10:51 AM
#4
Re: Sharing data between threads
john_avi,
There is no 'clean' way to cancel a thread on-demand. The only way to cancel threads is to signal for cancellation. When the thread receives the signal, it can then clean up and return out.
The concept is basically:
- 2 Threads (Thread A, Thread B)
- Thread A is your main thread, Thread B is worker thread
- Thread A starts Thread B
- User clicks Stop button in Thread A
- Thread A signals to Thread B to cancel
- Thread B (polluted with if checks on the cancellation request) receives the signal and when it gets to the next if (cancel), handles the cancellation and returns out
Personally IMO, cancelling threads in .NET is ugly and primitive, but it works and is the accepted pattern.
The BackgroundWorker class has a cancellation-like member in its DoWorkEventArgs class, which is passed to each worker thread. You can signal the Cancel (naming?) member from your main thread at any point. The caveat is that your worker thread _MUST_ be polluted with conditional checks for the cancellation member and handle it accordingly.
-
March 10th, 2010, 12:24 AM
#5
Re: Sharing data between threads
yeah u are right. I had to put a lot of if checks for cancel. Basically I was looking for a way to notify other thread which I am doing using events. I have created a delegate and an event, subscirbe my class object in worker thread for that event and whenever user clicks stop, I raise the event. Actually things are complex in my case because UI application here is an MFC application and working part is a com inerop dll. So things got little bit filthy. But finally I managed to do it.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|