2

I am sending SMS using following code through comport via gps modem

Thread thread = null;
private void btnsend_Click(object sender, EventArgs e)
    {
        if (thread == null)
        {                
            thread = new Thread(SendSms);
            thread.IsBackground = true;
            thread.Start();
        }
    }
    private void Update(int i)
    {
        if(InvokeRequired)
        {
            this.BeginInvoke(new Action<int>(Update), new Object[] {i});
            return;
        }
        using (var sp = new SerialPort("COM6"))
        {
            sp.Open();
            sp.WriteLine("AT" + Environment.NewLine);
            sp.WriteLine("AT+CMGF=1" + Environment.NewLine);
            sp.WriteLine("AT+CMGS=\"" + dt2.Rows[i]["PhoneNo"] + "\"" + Environment.NewLine);
            sp.WriteLine(tbsms.Text + (char)26);
            if (sp.BytesToRead > 0)
            {
                tbsentto.Text = i + 1 + " of " + dt2.Rows.Count;
            }
        }
    }
    private void SendSms()
    {
        for(int i = 0; i < dt2.Rows.Count; i++)
        {
            Update(i);
            Thread.Sleep(5000);
        }
        thread = null;
    }

my question is: how can i keep btnsend disabled till my thread is in progress so that user can not press btnsend to send sms to other recipients

kashif
  • 3,713
  • 8
  • 32
  • 47

3 Answers3

3

I had a similar issue in one of my own projects.

The solution I went for was as follows:

When I created the background workers for each button on the Form I assigned them DoWork and RunWorkerCompleted worker threads.

Then, on the thread triggered when the button is clicked, I also included a check to make sure that no worker threads were already running (including the one which the button itself triggered).

So my code looked like this:

private void XYZ_button_Click(object sender, EventArgs e)
{
    /* Check no background workers are already running */
    if ((XYZ_backgroundworker.IsBusy != true) &&
        (PQR_backgroundworker.IsBusy != true)) /* etc, etc for any other background
        workers you might have */
    {
        XYZ.RunWorkerAsync();
    }
}

private void XYZ_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null) MessageBox.Show("Error: " + e.Error.Message);
    else if (e.Cancelled == true) MessageBox.Show("Canceled!");
}

private void XYZ_DoWork(object sender, DoWorkEventArgs e)
{
    //Your code here
}

I'm assuming you know how to create background workers but, if not, you can find them in the toolbox on the form design page. You just select them from the list, click on the button you want to assign them to and voila! Then all you need to do is go to the events properties of the background worker and assign the apropriate worker threads.

In your specific case what you need to do is to create the background worker threads and move the contents of btnsend_Click to the DoWork thread. Then follow the format I've used above.

Hope this helps :)

GeorgePotter
  • 889
  • 1
  • 10
  • 18
  • Thanks GeorgePotter but my problem could not be resolved even by using your method. since my real coding is a little large, I'm editing an example of the same coding im desiring the solution of in my question. if the example is solved my problem will also be solved. when im pressing button1 in my above mentioned coding im getting this error. Cross-thread operation not valid: Control 'textBox1' accessed from a thread other than the thread it was created on. – kashif Apr 05 '12 at 15:49
  • Okay, first of all did you go into the properties of the bgw thread in the Form Design tab and go to the events properties (the little lightning icon) and assign the threads properly? I'm just going to recreate your example code and test it for myself and see if I can replicate your problem. – GeorgePotter Apr 05 '12 at 16:10
  • I've replicated your code but couldn't get the same error to show up. I couldn't get anything to appear in the textbox either but your error wasn't replicated. Unfortunately I'm literally about to go on holiday away from my computer for a few days so all I can suggest is that you implement the rest of the code the way I suggested and use messageboxes to display values. If you can get that bit working then you should be able to find solutions to your problem with the text box elsewhere. Also, there are some good background worker tutorials out there which might be of help. – GeorgePotter Apr 05 '12 at 16:22
  • Sorry I couldn't be of more assistance :S – GeorgePotter Apr 05 '12 at 16:22
  • Yes I've done everything exactly the way you directed me. im waiting for your response – kashif Apr 05 '12 at 16:28
  • Hmm. its ok i don't understand why did you not get the error im getting. anyways thanks at least you tried to help me if i found the solution i will update – kashif Apr 05 '12 at 16:31
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/9746/discussion-between-kashif-and-georgepotter) – kashif Apr 05 '12 at 22:09
1

You can call a function that in the end of the thread's action to enable the button. This is one easy way of doing it. But if you want to handle this more generically you can write a wrapper on Thread class or derive a new class from Thread class. In the new classes you can create events which will fire at the end of the thread's action completion.

Update:(After Hans Passant reminded me)

You can use BackGroundWorker. It does the same way I explained above. Register for the event WorkerCompleted which will be fire after the action is completed. Here is a small example

Prakash
  • 823
  • 12
  • 28
1

I found the solution of my question with the help of GeorgePotter. Thanks alot

private void btnsend_Click(object sender, EventArgs e)
    {
        foreach (Control c in Controls)
        {
            c.Enabled = false;
        }
        if (bgw.IsBusy == false)
        {
            bgw.RunWorkerAsync();
        }
    }
    private void Update(int i)
    {
        if (InvokeRequired)
        {
            this.BeginInvoke(new Action<int>(Update), new Object[] { i });
            return;
        }
        using (var sp = new SerialPort(cbcomport.Text))
        {
            sp.Open();
            sp.WriteLine("AT" + Environment.NewLine);
            sp.WriteLine("AT+CMGF=1" + Environment.NewLine);
            sp.WriteLine("AT+CMGS=\"" + dt.Rows[i]["PhoneNo"] + "\"" + Environment.NewLine);
            sp.WriteLine(tbsms.Text + (char)26);
            if (sp.BytesToRead > 0)
            {
                tbsentto.Text = i + 1 + " of " + dt.Rows.Count;
            }
        }
    }        
    private void bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            Update(i);
            Thread.Sleep(5000);
        }
    }
    private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        foreach (Control c in Controls)
        {
            c.Enabled = true;
        }
    }
kashif
  • 3,713
  • 8
  • 32
  • 47