Reputation: 87
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
Upvotes: 5
Views: 16347
Reputation: 4632
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.
Upvotes: 1
Reputation: 4856
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;
}
}
}
Upvotes: 0
Reputation: 2573
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.
Upvotes: 13
Reputation: 52107
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).
Upvotes: 0
Reputation: 17724
In the background worker you use the DoWork
event.
worker.DoWork += new DoWorkEventHandler(yourEventHandler);
void yourEventHandler(object sender, DoWorkEventArgs e)
{
//your work here
}
Upvotes: 3