我的代码是这样的:
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....";
}
}
上面的代码是读取传感器,即datarec = serialport_FT(0,1);函数在GUI端为我提供了一个传感器输出,稍后将用红色\绿色椭圆形描述(1-6)
问题:datarec = serialport_FT(0, 1);
此函数需要liltime,因此GUI会冻结,直到那个时候如何避免这种情况?
我尝试使用后台工作程序,但没有把这整个过程放到哪里 当进入ovalShape并更改其属性时,也遇到了交叉线程操作错误。
我没有得到在后台使用的函数的哪个部分以及何时何地返回第1个帖子
如果我必须使用线程
,请帮助我使用backgroundworker或使用invoke答案 0 :(得分:8)
你可以这样做:
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();
一项改进可能是将datarec
和rec_data
组合为args.Result中的元组。
答案 1 :(得分:2)
在后台工作程序中,您使用DoWork
事件。
worker.DoWork += new DoWorkEventHandler(yourEventHandler);
void yourEventHandler(object sender, DoWorkEventArgs e)
{
//your work here
}
答案 2 :(得分:1)
当您使用WinForms时,这是一篇很棒的MSDN文章,可以帮助您开始在应用程序中使用多个线程:Give Your .NET-based Application a Fast and Responsive UI with Multiple Threads
这篇文章“已有几天了”,但今天的原则仍然绝对有效。
如果您使用的是.NET 4.x版本,还可以使用Task Parallel Library更轻松地处理多个线程。
即将推出的.NET 4.5还提供了更加舒适的等待和asyc关键字:Asynchronous Programming with Async and Await。
答案 3 :(得分:0)
将它放在后台线程中,就像你已经尝试过的那样(或者更好的是Task),但要注意只能通过Control.Invoke(对于WinForms)或{{3来调用与GUI相关的操作。 (对于WPF)。
答案 4 :(得分:0)
使用标签随着任务的进展实时更新。你可以试试这个代码[使用BackGroundWorker]。查看DoWork
您放置业务逻辑的位置[请参阅代码中的BusinessClass
用法],然后查看后台任务在任务进行时实时向UI发送信号的ProgressChanged
&最后看到RunWorkerCompleted
在任务完成,错误或取消后处理代码的位置。
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;
}
}
}