Navdeep

I have simple example of one form application with a label,text box and button controls on it. Now the user enters digit in text box say 5. Click button and it counts 5 in 5 seconds. When the function count is counting 5. I want to call another function showlabel, which updates label with lapsed seconds. So I want to call one function from another function, which interacts with the control on the form. I am getting cross thread error.

Here is the code.



Code Block

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

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

// Async method beeps once per second
void Count(Object param)
{

Int32 seconds = (Int32)param;
for (Int32 index = 0; index < seconds; index++)
{
deleg_ShowLabel dlg = new deleg_ShowLabel(ShowLabel);
IAsyncResult iar = dlg.BeginInvoke(index,null,null);
Thread.Sleep(1000);
}

}
void ShowLabel(int i)
{
{
label.Text = (i + 1).ToString();
}
}
public delegate void deleg_ShowLabel(int i);

private void button1_Click(object sender, EventArgs e)
{
// Get an int from a string
Int32 count = 0;
try
{
count = Int32.Parse(text.Text);
}
catch (FormatException)
{
}

// Count to that number
//Count(count);
WaitCallback async = new WaitCallback(Count);
ThreadPool.QueueUserWorkItem(async, count);
}



}
}





Re: Windows Forms General Multithreading problem

Oleh Svintsitskyy

Hi Navdeep,

Your Count and ShowLabel functions should be updated to

Code Block

// Async method beeps once per second

void Count(Object param)

{

Int32 seconds = (Int32)param;

for (Int32 index = 0; index < seconds; index++)

{

ShowLabel(index);

Thread.Sleep(1000);

}

}

void ShowLabel(int i)

{

if (label.InvokeRequired)

{

deleg_ShowLabel dlg = new deleg_ShowLabel(ShowLabel);

this.Invoke(dlg,new object[]{ i});

}

else

{

label.Text = (i + 1).ToString();

}

}

Regards,

Oleh.





Re: Windows Forms General Multithreading problem

Navdeep

Hi Oleh,

Thanks for your inputs.
Its working the way I intended. The solution you corrected for me is the right way to achieve the result or there could be few more better or equally good ways to do it. I am new to multithreading.

Back to my first post, what my code actually meant in techincal terms ( although I know it was wrong ).

Thanks,
Navdeep





Re: Windows Forms General Multithreading problem

Oleh Svintsitskyy

Navdeep,

Since control have to be updated from the thread that created it You have to use Control.Invoke() method.It will ensure that delegate will be executed on the "correct" thread.

You did not ensure that delegate will be executed on the thread that created label control.

You were invoking it from the other thread than "label owner"

Code Block

WaitCallback async = new WaitCallback(Count);

ThreadPool.QueueUserWorkItem(async, count);

Code Block

deleg_ShowLabel dlg = new deleg_ShowLabel(ShowLabel);

IAsyncResult iar = dlg.BeginInvoke(index,null,null);

Regards,

Oleh.





Re: Windows Forms General Multithreading problem

Navdeep


this line of code is giving me strange error but it runs if I ignore. "Array creation must have array size or array initializer"
Strangely if I copy pasted from your code on forum it compiles and works fine. I can't see any difference what you just have written or what I have typed below is what I typed and copied from there and pasted here.

I am using F6 to build it

Code Block

this.Invoke(dlg, new object[] ( i ));





Re: Windows Forms General Multithreading problem

Carsten Kanstrup

You have used normal brackets () instead of curly brackets {}.





Re: Windows Forms General Multithreading problem

Navdeep

Carsten Kanstrup wrote:

You have used normal brackets () instead of curly brackets {}.



Thanks for pointing it out.