5

i have a code which is like this :

private void testToolStripMenuItem_Click(object sender, EventArgs e)
{
    toolStripStatusLabel1.Text = " Device Testing...";

    positive = false;

    clearsensors_gui();
    datarec = false;
    cmd = 04;
    datarec = serialport_FT(0, 1);

    if (datarec)
    {
        char ab = Convert.ToChar(rec_data[1]);
        //MessageBox.Show("\n" + ab + "\n");
        int cab = Convert.ToInt16(ab);
        int cabc1 = cab & 1;
        int cabc2 = cab & 2;
        int cabc3 = cab & 4;
        int cabc4 = cab & 8;
        int cabc5 = cab & 16;
        int cabc6 = cab & 32;

        if (cabc1 == 1)
            ovalShape1.FillColor = Color.Green;
        else
            ovalShape1.FillColor = Color.Red;

        if (cabc2 == 2)
            ovalShape2.FillColor = Color.Green;
        else
            ovalShape2.FillColor = Color.Red;

        if (cabc3 == 4)
            ovalShape3.FillColor = Color.Green;
        else
            ovalShape3.FillColor = Color.Red;

        if (cabc4 == 8)
            ovalShape4.FillColor = Color.Green;
        else
            ovalShape4.FillColor = Color.Red;

        if (cabc5 == 16)
            ovalShape5.FillColor = Color.Green;
        else
            ovalShape5.FillColor = Color.Red;

        if (cabc6 == 32)
            ovalShape6.FillColor = Color.Green;
        else
            ovalShape6.FillColor = Color.Red;

        toolStripStatusLabel1.Text = " Device Tested";
    }
    else
    {
        toolStripStatusLabel1.Text = "Try Again or Communication With Device Failure....";
    }
}

the above code is to read a the sensors i.e datarec = serialport_FT(0, 1); function provides me a sensor output at the GUI side which'll be later depicted with red\green ovalShapeX(1-6)

Question: datarec = serialport_FT(0, 1); this function takes liltime and so the GUI freezes till that time how to avoid this?

i tried using background worker but didn't get where to put this whole process also encountered with cross-threaded operation error when it goes to ovalShape and changing its properties.

I'm not getting what part of the function to be used in the background and where and when to get back to the 1st thread

please help me to use backgroundworker or use invoke if i have to use Threading

abatishchev
  • 98,240
  • 88
  • 296
  • 433
pdthekd
  • 87
  • 1
  • 1
  • 11
  • Put the call to serialport_FT() in a background thread - see http://stackoverflow.com/search?q=c%23+gui+background – Slugart Jun 26 '12 at 08:15
  • Use a backgroundworker, put `serialport_FT(0, 1)` in `DoWork()` and put `if (datarec) { ... }` inside the `Completed()` event. – H H Jun 26 '12 at 08:19
  • In order to avoid cross thread exception do something like this: http://stackoverflow.com/a/1136406/400303 – Mohammad Jun 26 '12 at 08:22
  • thank you for the reply going through all those docs – pdthekd Jun 26 '12 at 08:59

5 Answers5

13

You could do something like this:

toolStripStatusLabel1.Text = " Device Testing...";
positive = false;
clearsensors_gui();
datarec = false;
cmd = 04;

BackgroundWorker worker = new BackgroundWorker();

worker.DoWork += delegate(object s, DoWorkEventArgs args)
{
    // Will be run on background thread
    args.Result = serialport_FT(0, 1);
};

worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
    bool result = (bool)args.Result;

    if (result)
    {
        // Do your UI updates here
    }
};

worker.RunWorkerAsync();

One improvement could be to combine datarec and rec_data as a Tuple in args.Result.

ekholm
  • 2,543
  • 18
  • 18
  • thank you...tried this... i did not get any error this time but the UI din get updtated. I put the block: **if(datatarec){...}** under **if(result){...}**. What am i doing wrong? – pdthekd Jun 26 '12 at 09:46
  • Did you check that serialport_FT returned true and that result is true? – ekholm Jun 26 '12 at 10:00
  • yes result is true... so after that i call another function which has lines under **if(datarec){...}** [in question post] ovalShapesX[1-6] aren't updating neither giving me exceptions nor errors – pdthekd Jun 26 '12 at 10:12
  • Hmm... And the data looks ok I pressume? Did the UI stuff work before? Is the text field updated? – ekholm Jun 26 '12 at 10:20
  • data is ok ,used **toolStripStatusLabel1.Text = "tested";** after the function is done calling, which is displayed. the code which i have posted above is a working 1 except for a small freeze point in while executing datarec= serial_FT(0,1); so i wanted to use background worker now – pdthekd Jun 26 '12 at 10:32
  • So the label is updated, but not the shapes? Maybe they need a `Refresh()` – ekholm Jun 26 '12 at 10:51
  • Can't see what's wrong here. In RunWorkerCompleted you are back on the UI thread, so it shouldn't be a problem. You have set `ovalShapeX.FillStyle = FillStyle.Solid`? Could you post your current code? – ekholm Jun 26 '12 at 12:22
  • thaks man .... **ovalShapeX.FillStyle = FillStyle.Solid** , i had missed this while writing the function again with backgroundworker... Thank u loads – pdthekd Jun 27 '12 at 05:58
3

In the background worker you use the DoWork event.

worker.DoWork += new DoWorkEventHandler(yourEventHandler); 

void yourEventHandler(object sender, DoWorkEventArgs e)
{
//your work here
}
nunespascal
  • 17,584
  • 2
  • 43
  • 46
1

As you are using WinForms, here is a great MSDN article to get you started with using multiple threads in an application: Give Your .NET-based Application a Fast and Responsive UI with Multiple Threads

The article is 'a few days old', but the principles remain absolutely valid today.

If you are working in a .NET 4.x version, you can also use the Task Parallel Library to make working with multiple threads easier.

The upcoming .NET 4.5 also offers the even more comfortable await and asyc keywords: Asynchronous Programming with Async and Await.

Jens H
  • 4,590
  • 2
  • 25
  • 35
0

Put this in a background thread as you already tried (or better yet, a Task), but be careful to call GUI-related operations only through Control.Invoke (for WinForms) or Dispatcher.Invoke (for WPF).

Branko Dimitrijevic
  • 50,809
  • 10
  • 93
  • 167
0

Used a Label which updates in real time as the task progresses. You can try this code [using BackGroundWorker]. Look at DoWork where you put your business logic [See BusinessClass usage in the code], then see the ProgressChanged where the background task signals the UI in real time as the task progresses & finally see the RunWorkerCompleted where you handle code after task completion, error or cancellation.

using System.ComponentModel;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form3 : Form
    {
        private BackgroundWorker _worker;
        BusinessClass _biz = new BusinessClass();
        public Form3()
        {
            InitializeComponent();
            InitWorker();
        }

        private void InitWorker()
        {
            if (_worker != null)
            {
                _worker.Dispose();
            }

            _worker = new BackgroundWorker
            {
                WorkerReportsProgress = true,
                WorkerSupportsCancellation = true
            };
            _worker.DoWork += DoWork;
            _worker.RunWorkerCompleted += RunWorkerCompleted;
            _worker.ProgressChanged += ProgressChanged;
            _worker.RunWorkerAsync();
        }


        void DoWork(object sender, DoWorkEventArgs e)
        {
            int highestPercentageReached = 0;
            if (_worker.CancellationPending)
            {
                e.Cancel = true;
            }
            else
            {
                double i = 0.0d;
                int junk = 0;
                for (i = 0; i <= 199990000; i++)
                {
                    int result = _biz.MyFunction(junk);
                    junk++;

                    // Report progress as a percentage of the total task.
                    var percentComplete = (int)(i / 199990000 * 100);
                    if (percentComplete > highestPercentageReached)
                    {
                        highestPercentageReached = percentComplete;
                        // note I can pass the business class result also and display the same in the LABEL  
                        _worker.ReportProgress(percentComplete, result);
                        _worker.CancelAsync();
                    }
                }

            }
        }

        void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                // Display some message to the user that task has been
                // cancelled
            }
            else if (e.Error != null)
            {
                // Do something with the error
            }
        }

        void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            label1.Text =  string.Format("Result {0}: Percent {1}",e.UserState, e.ProgressPercentage);
        }
    }

    public class BusinessClass
    {
        public int MyFunction(int input)
        {
            return input+10;
        }
    }
}
Angshuman Agarwal
  • 4,796
  • 7
  • 41
  • 89